public static ClickTasktrayIcon ( string tooltip ) : bool | ||
tooltip | string | |
return | bool |
public static bool ClickTasktrayIcon(string tooltip)
{
const string TRAY_WINDOW = "Shell_TrayWnd";
const string TRAY_NOTIFYWINDOW = "TrayNotifyWnd";
const string TRAY_PAGER = "SysPager";
const string TOOLBAR_CONTROL = "ToolbarWindow32";
//タスクバーのハンドル取得
var taskbarWin = FindWindow(TRAY_WINDOW, null);
if (taskbarWin.Equals(IntPtr.Zero)) return false;
//通知領域のハンドル取得
var trayWin = FindWindowEx(taskbarWin, IntPtr.Zero, TRAY_NOTIFYWINDOW, null);
if (trayWin.Equals(IntPtr.Zero)) return false;
//SysPagerの有無確認。(XP/2000はSysPagerあり)
var tempWin = FindWindowEx(trayWin, IntPtr.Zero, TRAY_PAGER, null);
if (tempWin.Equals(IntPtr.Zero)) tempWin = trayWin;
//タスクトレイがツールバーで出来ているか確認
// → ツールバーでなければ終了
var toolWin = FindWindowEx(tempWin, IntPtr.Zero, TOOLBAR_CONTROL, null);
if (toolWin.Equals(IntPtr.Zero)) return false;
//タスクトレイのプロセス(Explorer)を取得し、外部から参照するために開く
int expPid = 0;
GetWindowThreadProcessId(toolWin, out expPid);
var hProc = OpenProcess(ProcessAccess.VMOperation | ProcessAccess.VMRead | ProcessAccess.VMWrite, false, expPid);
if (hProc.Equals(IntPtr.Zero)) return false;
//プロセスを閉じるためにtry-finally
try
{
var tbButtonLocal = new TBBUTTON(); //本プロセス内のタスクバーボタン情報作成(サイズ特定でのみ使用)
//Explorer内のタスクバーボタン格納メモリ確保
var ptbSysButton = VirtualAllocEx(hProc, IntPtr.Zero, (IntPtr)Marshal.SizeOf(tbButtonLocal), AllocationTypes.Reserve | AllocationTypes.Commit, MemoryProtectionTypes.ReadWrite);
if (ptbSysButton.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
try
{
var tbButtonInfoLocal = new TBBUTTONINFO(); //本プロセス内ツールバーボタン詳細情報作成
//Explorer内のタスクバーボタン詳細情報格納メモリ確保
var ptbSysInfo = VirtualAllocEx(hProc, IntPtr.Zero, (IntPtr)Marshal.SizeOf(tbButtonInfoLocal), AllocationTypes.Reserve | AllocationTypes.Commit, MemoryProtectionTypes.ReadWrite);
if (ptbSysInfo.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
try
{
const int titleSize = 256; //Tooltip文字列長
var title = ""; //Tooltip文字列
//共有メモリにTooltip読込メモリ確保
var pszTitle = Marshal.AllocCoTaskMem(titleSize);
if (pszTitle.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
try
{
//Explorer内にTooltip読込メモリ確保
var pszSysTitle = VirtualAllocEx(hProc, IntPtr.Zero, (IntPtr)titleSize, AllocationTypes.Reserve | AllocationTypes.Commit, MemoryProtectionTypes.ReadWrite);
if (pszSysTitle.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
try
{
//通知領域ボタン数取得
var iCount = (int)SendMessage(toolWin, (int)Sm_Message.TB_BUTTONCOUNT, new IntPtr(0), new IntPtr(0));
//左から順に情報取得
for (var i = 0; i < iCount; i++)
{
var dwBytes = 0; //読み書きバイト数
var tbButtonLocal2 = new TBBUTTON(); //ボタン情報
var tbButtonInfoLocal2 = new TBBUTTONINFO(); //ボタン詳細情報
//共有メモリにボタン情報読込メモリ確保
var ptrLocal = Marshal.AllocCoTaskMem(Marshal.SizeOf(tbButtonLocal));
if (ptrLocal.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
try
{
Marshal.StructureToPtr(tbButtonLocal, ptrLocal, true); //共有メモリ初期化
//ボタン情報取得(idCommandを取得するため)
SendMessage(
toolWin,
(int)Sm_Message.TB_GETBUTTON,
new IntPtr(i),
ptbSysButton);
//Explorer内のメモリを共有メモリに読み込み
ReadProcessMemory(
hProc,
ptbSysButton,
ptrLocal,
(IntPtr)Marshal.SizeOf(tbButtonLocal),
out dwBytes);
//共有メモリの内容を構造体に変換
tbButtonLocal2 = (TBBUTTON)Marshal.PtrToStructure(
ptrLocal,
typeof(TBBUTTON));
}
finally
{
Marshal.FreeCoTaskMem(ptrLocal); //共有メモリ解放
}
//ボタン詳細情報を取得するためのマスク等を設定
tbButtonInfoLocal.cbSize = Marshal.SizeOf(tbButtonInfoLocal);
tbButtonInfoLocal.dwMask = (int)(ToolbarButtonMask.TBIF_COMMAND | ToolbarButtonMask.TBIF_LPARAM | ToolbarButtonMask.TBIF_TEXT);
tbButtonInfoLocal.pszText = pszSysTitle; //Tooltip書き込み先領域
tbButtonInfoLocal.cchText = titleSize;
//マスク設定等をExplorerのメモリへ書き込み
WriteProcessMemory(
hProc,
ptbSysInfo,
ref tbButtonInfoLocal,
(IntPtr)Marshal.SizeOf(tbButtonInfoLocal),
out dwBytes);
//ボタン詳細情報取得
SendMessage(
toolWin,
(int)Sm_Message.TB_GETBUTTONINFO,
tbButtonLocal2.idCommand,
ptbSysInfo);
//共有メモリにボタン詳細情報を読み込む領域確保
var ptrInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(tbButtonInfoLocal));
if (ptrInfo.Equals(IntPtr.Zero)) return false; //共有メモリ確保失敗
try
{
Marshal.StructureToPtr(tbButtonInfoLocal, ptrInfo, true); //共有メモリ初期化
//Explorer内のメモリを共有メモリに読み込み
ReadProcessMemory(
hProc,
ptbSysInfo,
ptrInfo,
(IntPtr)Marshal.SizeOf(tbButtonInfoLocal),
out dwBytes);
//共有メモリの内容を構造体に変換
tbButtonInfoLocal2 = (TBBUTTONINFO)Marshal.PtrToStructure(
ptrInfo,
typeof(TBBUTTONINFO));
}
finally
{
Marshal.FreeCoTaskMem(ptrInfo); //共有メモリ解放
}
//Tooltipの内容をExplorer内のメモリから共有メモリへ読込
ReadProcessMemory(hProc, pszSysTitle, pszTitle, (IntPtr)titleSize, out dwBytes);
//ローカル変数へ変換
title = Marshal.PtrToStringAnsi(pszTitle, titleSize);
//Tooltipが指定文字列を含んでいればクリック
if (title.Contains(tooltip))
{
//PostMessageでクリックを送るために、ボタン詳細情報のlParamでポイントされているTRAYNOTIFY情報が必要
var tNotify = new TRAYNOTIFY();
var tNotify2 = new TRAYNOTIFY();
//共有メモリ確保
var ptNotify = Marshal.AllocCoTaskMem(Marshal.SizeOf(tNotify));
if (ptNotify.Equals(IntPtr.Zero)) return false; //メモリ確保失敗
try
{
Marshal.StructureToPtr(tNotify, ptNotify, true); //初期化
//lParamのメモリを読込
ReadProcessMemory(
hProc,
tbButtonInfoLocal2.lParam,
ptNotify,
(IntPtr)Marshal.SizeOf(tNotify),
out dwBytes);
//構造体へ変換
tNotify2 = (TRAYNOTIFY)
Marshal.PtrToStructure(
ptNotify,
typeof(TRAYNOTIFY));
}
finally
{
Marshal.FreeCoTaskMem(ptNotify); //共有メモリ解放
}
//クリックするためには通知領域がアクティブでなければならない
SetForegroundWindow(tNotify2.hWnd);
//左クリック
PostMessage(tNotify2.hWnd, tNotify2.uCallbackMessage, (IntPtr)tNotify2.uID, (IntPtr)PM_Message.WM_LBUTTONDOWN);
PostMessage(tNotify2.hWnd, tNotify2.uCallbackMessage, (IntPtr)tNotify2.uID, (IntPtr)PM_Message.WM_LBUTTONUP);
return true;
}
}
return false; //該当なし
}
finally
{
VirtualFreeEx(hProc, pszSysTitle, (IntPtr)titleSize, MemoryFreeTypes.Release); //メモリ解放
}
}
finally
{
Marshal.FreeCoTaskMem(pszTitle); //共有メモリ解放
}
}
finally
{
VirtualFreeEx(hProc, ptbSysInfo, (IntPtr)Marshal.SizeOf(tbButtonInfoLocal), MemoryFreeTypes.Release); //メモリ解放
}
}
finally
{
VirtualFreeEx(hProc, ptbSysButton, (IntPtr)Marshal.SizeOf(tbButtonLocal), MemoryFreeTypes.Release); //メモリ解放
}
}
finally
{
CloseHandle(hProc); //Explorerのプロセス閉じる
}
}
private static void ShowPreviousWindow() { // 実行中の同じアプリケーションのウィンドウ・ハンドルの取得 var prevProcess = Win32Api.GetPreviousProcess(); if (prevProcess != null && prevProcess.MainWindowHandle == IntPtr.Zero) { // 起動中のアプリケーションを最前面に表示 Win32Api.WakeupWindow(prevProcess.MainWindowHandle); } else { if (prevProcess != null) { //プロセス特定は出来たが、ウィンドウハンドルが取得できなかった(アイコン化されている) //タスクトレイアイコンのクリックをエミュレート //注:アイコン特定はTooltipの文字列で行うため、多重起動時は先に見つけた物がアクティブになる var rslt = Win32Api.ClickTasktrayIcon(Application.ProductName); if (!rslt) { // 警告を表示(見つからない、またはその他の原因で失敗) MessageBox.Show(MyCommon.ReplaceAppName(Properties.Resources.StartupText1), MyCommon.ReplaceAppName(Properties.Resources.StartupText2), MessageBoxButtons.OK, MessageBoxIcon.Information); } } else { // 警告を表示(プロセス見つからない場合) MessageBox.Show(MyCommon.ReplaceAppName(Properties.Resources.StartupText1), MyCommon.ReplaceAppName(Properties.Resources.StartupText2), MessageBoxButtons.OK, MessageBoxIcon.Information); } } }