- [SQLSERVER] Loại bỏ Restricted User trên database MSSQL
- [C#] Hướng dẫn tạo mã QRcode Style trên winform
- [C#] Hướng dẫn sử dụng temp mail service api trên winform
- [C#] Hướng dẫn tạo mã thanh toán VietQR Pay không sử dụng API trên winform
- [C#] Hướng Dẫn Tạo Windows Service Đơn Giản Bằng Topshelf
- [C#] Chia sẻ source code đọc dữ liệu từ Google Sheet trên winform
- [C#] Chia sẻ source code tạo mã QR MOMO đa năng Winform
- [C#] Chia sẻ source code phần mềm lên lịch tự động chạy ứng dụng Scheduler Task Winform
- [Phần mềm] Tải và cài đặt phần mềm Sublime Text 4180 full version
- [C#] Hướng dẫn download file từ Minio Server Winform
- [C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform
- [SOFTWARE] Phần mềm gởi tin nhắn Zalo Marketing Pro giá rẻ mềm nhất thị trường
- [C#] Việt hóa Text Button trên MessageBox Dialog Winform
- [DEVEXPRESS] Chia sẻ code các tạo report in nhiều hóa đơn trên XtraReport C#
- [POWER AUTOMATE] Hướng dẫn gởi tin nhắn zalo từ file Excel - No code
- [C#] Chia sẻ code lock và unlock user trong domain Window
- [DEVEXPRESS] Vẽ Biểu Đồ Stock Chứng Khoán - Công Cụ Thiết Yếu Cho Nhà Đầu Tư trên Winform
- [C#] Hướng dẫn bảo mật ứng dụng 2FA (Multi-factor Authentication) trên Winform
- [C#] Hướng dẫn convert HTML code sang PDF File trên NetCore 7 Winform
- [C#] Hướng dẫn viết ứng dụng chat với Gemini AI Google Winform
[C#] Hook Right context menu windows (ex: Pin and Unpin Taskbar)
Xin chào các bạn, bài viết hôm nay mình sẽ hướng dẫn các bạn cách Hook Menu chuột phải Context Menu của từng ứng dụng trên Windows Explorer C#.
[C#] Hook Right context menu windows (ex: Pin and Unpin Taskbar)
Cụ thể ở bài viết demo này chức năng Pin và UnPin một ứng dụng vào thanh taskbar Windows.
Trên từng item của mỗi menu trong windows explorer sẽ có một mã ID.
Vd:
pin to taskbar => 5386
Unpin from taskbar => 5387
Các bạn có thể tham khảo thêm các mã khác ở link sau:
http://www.win7dll.info/shell32_dll.html
Các bạn xem giao diện demo ứng dụng mình dưới đây:
Trong bài viết này các bạn nhìn hình ở trên khi mình right click chuột phải vào ứng dụng HOB 2015.exe, thì các bạn thấy được một danh sách treeview mình trả về giống hình bên tay phải các bạn.
Khi các bạn nhấn vào từng item node trên treeview này nó sẽ thực hiện hành động (action) giống như khi các bạn click vào menu trên windows explorer vậy.
Để pin được ứng dụng vào thanh taskbar, các bạn phải cần giả lập ứng dụng của bạn đang chạy là "Windows Explorer" thì nó mới cho phép.
Nên trong bài viết mình có để hàm sẵn trên là ChangeImagePathName()
và truyền vào là đường dẫn của Windows Explorer, nếu các bạn không thêm hàm này vào sẽ không thấy được menu Pin to Taskbar nhé.
Demo ứng dụng Pin and unPin taskbar C#:
Đầu tiên các bạn cần tạo một class Utils.cs, với nội dung như sau:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PinToTaskbar
{
static public class Utils
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);
public static List<string> PinUnpinTaskbar(string filePath, bool pin, string action = "")
{
if (!File.Exists(filePath)) throw new FileNotFoundException(filePath);
int MAX_PATH = 255;
var actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
IntPtr hShell32 = LoadLibrary("Shell32.dll");
LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
string localizedVerb = szPinToStartLocalized.ToString();
string path = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileName(filePath);
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
dynamic directory = shellApplication.NameSpace(path);
dynamic link = directory.ParseName(fileName);
List<string> lists = new List<string>();
dynamic verbs = link.Verbs();
for (int i = 0; i < verbs.Count(); i++)
{
dynamic verb = verbs.Item(i);
var name = verb.Name;
lists.Add(name);
if (string.IsNullOrEmpty(action))
{
if (verb.Name.Equals(localizedVerb))
{
verb.DoIt();
}
}
else
{
if (verb.Name.Equals(action))
{
verb.DoIt();
}
}
}
return lists;
}
static string originalImagePathName;
static int unicodeSize = IntPtr.Size * 2;
static bool changed;
static void GetPointers(out IntPtr imageOffset, out IntPtr imageBuffer)
{
IntPtr pebBaseAddress = GetBasicInformation().PebBaseAddress;
var processParameters = Marshal.ReadIntPtr(pebBaseAddress, 4 * IntPtr.Size);
imageOffset = processParameters.Increment(4 * 4 + 5 * IntPtr.Size + unicodeSize + IntPtr.Size + unicodeSize);
imageBuffer = Marshal.ReadIntPtr(imageOffset, IntPtr.Size);
}
internal static void ChangeImagePathName(string newFileName)
{
IntPtr imageOffset, imageBuffer;
GetPointers(out imageOffset, out imageBuffer);
var imageLen = Marshal.ReadInt16(imageOffset);
originalImagePathName = Marshal.PtrToStringUni(imageBuffer, imageLen / 2);
var newImagePathName = Path.Combine(Path.GetDirectoryName(originalImagePathName), newFileName);
if (newImagePathName.Length > originalImagePathName.Length) throw new Exception("new ImagePathName cannot be longer than the original one");
var ptr = imageBuffer;
foreach (var unicodeChar in newImagePathName)
{
Marshal.WriteInt16(ptr, unicodeChar);
ptr = ptr.Increment(2);
}
changed = true;
Marshal.WriteInt16(ptr, 0);
Marshal.WriteInt16(imageOffset, (short)(newImagePathName.Length * 2));
}
internal static void RestoreImagePathName()
{
if (!changed) return;
IntPtr imageOffset, ptr;
GetPointers(out imageOffset, out ptr);
foreach (var unicodeChar in originalImagePathName)
{
Marshal.WriteInt16(ptr, unicodeChar);
ptr = ptr.Increment(2);
}
Marshal.WriteInt16(ptr, 0);
Marshal.WriteInt16(imageOffset, (short)(originalImagePathName.Length * 2));
}
public static ProcessBasicInformation GetBasicInformation()
{
uint status;
ProcessBasicInformation pbi;
int retLen;
var handle = System.Diagnostics.Process.GetCurrentProcess().Handle;
if ((status = NtQueryInformationProcess(handle, 0,
out pbi, Marshal.SizeOf(typeof(ProcessBasicInformation)), out retLen)) >= 0xc0000000)
throw new Exception("Windows exception. status=" + status);
return pbi;
}
[DllImport("ntdll.dll")]
public static extern uint NtQueryInformationProcess(
[In] IntPtr ProcessHandle,
[In] int ProcessInformationClass,
[Out] out ProcessBasicInformation ProcessInformation,
[In] int ProcessInformationLength,
[Out] [Optional] out int ReturnLength
);
public static IntPtr Increment(this IntPtr ptr, int value)
{
unchecked
{
if (IntPtr.Size == sizeof(Int32))
return new IntPtr(ptr.ToInt32() + value);
else
return new IntPtr(ptr.ToInt64() + value);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct ProcessBasicInformation
{
public uint ExitStatus;
public IntPtr PebBaseAddress;
public IntPtr AffinityMask;
public int BasePriority;
public IntPtr UniqueProcessId;
public IntPtr InheritedFromUniqueProcessId;
}
}
}
Và dưới đây là source code của form chính:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PinToTaskbar
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string filename;
private void btn_pinTaskbar_Click(object sender, EventArgs e)
{
filename = @"C:Program Files (x86)HOABINH COMPANY LIMITEDHOB METRO UI 2018HOB 2015.exe";
List<string> list = new List<string>();
treeView.Nodes.Clear();
try
{
Utils.ChangeImagePathName(@"C:Windowsexplorer.exe");
list = Utils.PinUnpinTaskbar(filename, true);
}
finally
{
Utils.RestoreImagePathName();
}
foreach (var item in list)
{
TreeNode newNode = new TreeNode(item);
treeView.Nodes.Add(newNode);
}
}
private void btn_unpin_Click(object sender, EventArgs e)
{
Utils.ChangeImagePathName("explorer.exe");
List<string> list = new List<string>();
list.Clear();
list = Utils.PinUnpinTaskbar(filename, false);
treeView.Nodes.Clear();
foreach (var item in list)
{
TreeNode newNode = new TreeNode(item);
treeView.Nodes.Add(newNode);
}
}
private void treeView_AfterSelect(object sender, TreeViewEventArgs e)
{
var text = e.Node.Text;
Utils.PinUnpinTaskbar(filename, false, text);
}
}
}
Thanks for watching!