- [DEVEXPRESS] Hướng dẫn bật tính năng Scroll Pixcel in Touch trên GridView
- [DEVEXPRESS] Hướng dẫn sử dụng TileBar viết ứng dụng duyệt hình ảnh Winform
- [DEVEXPRESS] Tô màu border TextEdit trên Winform
- [C#] Lấy dữ liệu từ Console Write hiển thị lên textbox Winform
- [C#] Hiển thị Progress bar trên Window Console
- [C#] Di chuyển control Runtime và lưu layout trên winform
- [SQLSERVER] Sử dụng hàm NULL IF
- [C#] Chia sẽ source code mã đi tuần bằng giao diện Winform
- [C#] Flash Window in Taskbar Winform
- Download và Giải nén tập tin File sử dụng Powershell
- [C#] Hướng dẫn cách lấy thông tin đăng nhập tài khoản và mật khẩu web browser trên windows
- [VB.NET] CRUD Thêm xóa sửa tìm kiếm Realtime FireBase
- [C#] Hiển thị thông báo Toast Message trong lập trình Winform
- [C#] Cấu hình định dạng ngày tháng, thời gian trên Windows cho ứng dụng Winform
- [C#] Rút gọn đường dẫn link url với TinyURL API
- [C#] Hướng dẫn cách bo tròn winform with Radius
- [C#] Chia sẽ class BackGroundOverlay Show Modal cho Winform
- [C#] Hướng dẫn Flip Image Winform
- [C#] Invoke là gì? cách sử dụng phương thức Invoke()
- [C#] Hướng dẫn chia sẽ file, folder từ ứng dụng sang Zalo Chat
[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!