- [DEVEXPRESS] Chia sẻ source code cách tạo biểu đồ sơ đồ tổ chức công ty Org Chart trên Winform C#
- [C#] Hướng dẫn tạo Auto Number trên Datagridview winform
- [DATABASE] Hướng dẫn tạo Procedure String Split in Mysql
- [C#] Thiết lập dấu (,) hay dấu (.) ở định dạng số đúng với định dạng số Việt Nam
- [C#] Chia sẻ source code Game Spin Lucky Wheel
- [C#] Hướng dẫn Encode and Decode HTML
- Hướng dẫn tạo tài khoản Chat Open AI GPT tại Việt Nam
- [C#] Hướng dẫn thay đổi giao diện ứng dụng Winform theo giao diện của Windows
- [VB.NET] Hiệu ứng Acrylic, Mica, Tabbed Blur Effect trên Winform
- [DEVEXPRESS] Hướng dẫn sử dụng HTML Template trên Combobox Edit
- [C#] Chia sẻ source code Orange Rain in Winform
- [DEVEXPRESS] Hướng dẫn sử dụng HTML Template trên XtraMessageBox Winform Devexpress 22.2.3
- [DEVEXPRESS] Hướng dẫn sử dụng HTML and CSS Code Viewer trên Winform
- [C#] Number Effect Counter up and down in winform
- [C#] Hướng dẫn Supend and Resume Process ID in Winform
- [C#] Hiển thị line number trên Richtextbox Winform
- [C#] Fake Blue Screen BSOD in winform
- [C#] Chia sẽ code demo sử dụng Async Parallel Foreach and For in Winform
- [C#] Sử dụng ActionBlock run X task at time winform
- [C#] Hướng dẫn sử dụng Property Grid để lưu và tải lại thông tin cấu hình user trên 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!