【发布时间】:2014-09-12 11:49:46
【问题描述】:
我在只运行一个窗口实例时遇到了问题。
实现细节:我有一个 C++ 应用程序,它在任务栏中显示为一个图标。在双击图标时,我正在使用 ShellExecuteW 函数打开一个新的 delphi 窗口。现在我实现了一个逻辑,即每当用户双击图标时,它只打开一个窗口实例,避免启动多个窗口。如果用户双击该图标,并且已经打开了一个窗口,它只会将窗口带到最前面,或者如果它被最小化,它将恢复窗口。
下面的代码展示了我是如何实现上述逻辑的,它是在双击图标时触发的:
///////////////////////Double Click Code starts/////////////////////////
HWND hWnd = NULL;
HWND hWndFirst = NULL;
DWORD dw = FindProcessId("abc.exe");
if(dw == 0)
{
//Open new window
ShellExecuteW(0, L"open", acExePath, acParams, acFullPath, SW_SHOW);
hWndFirst = NULL;
}
else
{
//Open existing window
hWnd = hGetWindowHandleOfProcess(dw);
if(hWndFirst == NULL) hWndFirst = hWnd;
if(hWndFirst != hWnd)
{
//This is just a small work-around as minimizing the window was changing
//it's window handle. So I preserve the window handle the first time and
//use it whenever the window is minimized (i.e. the handle is changed)
SetForegroundWindow(hWndFirst);
ShowWindow(hWndFirst, SW_RESTORE);
}
else
{
SetForegroundWindow(hWnd);
ShowWindow(hWnd, SW_RESTORE);
}
}
///////////////////////Double Click Code ends///////////////////////////
///////////////////////Supporting functions/////////////////////////
struct ProcessHandleData
{
unsigned long lProcessId;
HWND hProcessWindowHandle;
};
//Finds the process id when given the process name
DWORD FindProcessId(char* pcProcessName)
{
char* pcBegin = strrchr(pcProcessName, '\\');
if(pcBegin)
pcProcessName = pcBegin+1;
PROCESSENTRY32 sProcessInfo;
sProcessInfo.dwSize = sizeof(sProcessInfo);
HANDLE sProcessesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if ( sProcessesSnapshot == INVALID_HANDLE_VALUE )
return 0;
Process32First(sProcessesSnapshot, &sProcessInfo);
if ( !strcmp(pcProcessName, sProcessInfo.szExeFile) )
{
CloseHandle(sProcessesSnapshot);
return sProcessInfo.th32ProcessID;
}
while ( Process32Next(sProcessesSnapshot, &sProcessInfo) )
{
if ( !strcmp(pcProcessName, sProcessInfo.szExeFile) )
{
CloseHandle(sProcessesSnapshot);
return sProcessInfo.th32ProcessID;
}
}
CloseHandle(sProcessesSnapshot);
return 0;
}
//Search predicate for EnumWindows function
BOOL CALLBACK bEnumWindowsSearcher(HWND handle, LPARAM lParam)
{
ProcessHandleData& sProcesshandleData = *(ProcessHandleData*)lParam;
unsigned long lProcessId = 0;
GetWindowThreadProcessId(handle, &lProcessId);
if (sProcesshandleData.lProcessId != lProcessId)
return true;
sProcesshandleData.hProcessWindowHandle = handle;
return false;
}
//Gets the window handle of the process (input process id)
HWND hGetWindowHandleOfProcess(unsigned long lProcessId)
{
ProcessHandleData sProcessHandleData;
sProcessHandleData.lProcessId = lProcessId;
sProcessHandleData.hProcessWindowHandle = 0;
EnumWindows(bEnumWindowsSearcher, (LPARAM)&sProcessHandleData); //enumerate all windows
return sProcessHandleData.hProcessWindowHandle;
}
问题: 上面的代码可以正常工作。但是我面临一个问题。如果打开的窗口未处于活动状态或位于任何窗口后面,则上述代码会将其置于前面(如预期的那样)。但是如果我最小化窗口并双击图标,它会恢复窗口并将其带到前面(再次如预期的那样)。但是在此操作之后,我不再能够使用窗口右上角的最小化栏来最小化窗口。某些东西会禁用(不是物理上)窗口的最小化栏。
非常感谢您在这方面的帮助。如果您需要有关该问题的更多信息,请告诉我。
非常感谢。
PS:上面的代码不完全是我的,我已经研究了各种网站以获得运行问题的各个部分的代码。
【问题讨论】: