防止程序重复打开,如果已经打开,则最大化已打开窗口。诡异问题出现!

时间:2021-05-25 18:57:37
防止程序重复打开,如果已经打开,则最大化已打开前一个程序,把窗口最大化。诡异问题出现!

以下代码放在BOOL CxxxApp::InitInstance()中


BOOL bAlreadyRunning;
HANDLE hMutexOneInstance = CreateMutex(NULL,FALSE,_T("706238C88F98"));
bAlreadyRunning = (GetLastError() == ERROR_ALREADY_EXISTS);
if(hMutexOneInstance)
ReleaseMutex(hMutexOneInstance);

if(bAlreadyRunning)
{
    DWORD Pid = 0;
    Pid = GetProcessidFromName("are.exe");//根据进程名获得进程ID
    HWND hwnd = NULL;
    hwnd = GetWindowHandleByPID(Pid);//根据进程ID获得窗口句柄
    if (NULL! = hwnd)
    {
::ShowWindow(hwnd,SW_SHOWMAXIMIZED); //窗口最大化
    }

    exit(NULL); //退出程序
              return FALSE; 
}

当打开第二次时,可以将前面打开的程序最大化,但是问题出来了,最大化的程序窗口不再响应鼠标消息,鼠标点上去没有任何反应,但是能响应键盘消息。

请问是什么原因呢?
有没有其他成熟的代码实现该功能,即防止软件重复打开,如果判断已经打开,那把第一个转到前台,最大化。

14 个解决方案

#1


HANDLE m_hMutex=CreateMutex(NULL,TRUE,"s1231254353535dd");
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
//AfxMessageBox("该程序已经运行",MB_ICONEXCLAMATION);
ExitProcess(0);
// return FALSE;
}
防止重复打开为什么还要让打开呢?
在BOOL CXXXXApp::InitInstance()加上上面这句好不?直接关闭。。

#2


用线程让前一个程序等待消息,再次打开可以用上段程序判断到,向前一个程序发送消息。。

#3


::ShowWindow(hwnd,SW_SHOWMAXIMIZED);

换成这样试下。
 PostMessage(hWnd, WM_SHOWWINDOW,(WPARAM)TRUE, (LPARAM)SW_OTHERZOOM)

#4


引用 3 楼 zwfgdlc 的回复:
::ShowWindow(hwnd,SW_SHOWMAXIMIZED);

换成这样试下。
 PostMessage(hWnd, WM_SHOWWINDOW,(WPARAM)TRUE, (LPARAM)SW_OTHERZOOM)

谢谢回答,不过消息好像没有传递给hwnd。没有反应。如何让前一个程序响应本程序的消息呢?

#5


引用 2 楼 afairycell 的回复:
用线程让前一个程序等待消息,再次打开可以用上段程序判断到,向前一个程序发送消息。。

谢谢!请问如何让前一个程序等待消息?

#6


引用 1 楼 afairycell 的回复:
HANDLE m_hMutex=CreateMutex(NULL,TRUE,"s1231254353535dd");
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
//AfxMessageBox("该程序已经运行",MB_ICONEXCLAMATION);
ExitProcess(0);
// return FALSE;
}
防止重复打开为什么还要让打开呢?
在BOOL CXXXXApp::InitInstance()加上上面这句好不?直接关闭。。


是把已经打开的那个程序最大化,你上面的给的代码是判断已经打开了程序,直接退出,我是想增加个功能,退出前把已经打开的程序最大化,再退出

#7


把他激活到置顶窗口就行了。

#8


Pid = GetProcessidFromName("are.exe");//根据进程名获得进程ID
        HWND hwnd = NULL;
        hwnd = GetWindowHandleByPID(Pid);//根据进程ID获得窗口句柄
--------------------------
你的这两个得到的HWND句柄对吗?

#9


HANDLE hMutex = CreateMutex(NULL, FALSE, _T("XXXXXXXXX"));
if((NULL != hMutex) && (ERROR_ALREADY_EXISTS == GetLastError()))
{
HWND hWnd = ::FindWindow(NULL, _T("XXXXX"));
if(NULL != hWnd)
{
ShowWindow(hWnd, SW_MAXIMIZE);
}
CloseHandle(hMutex);
return FALSE;
}

#10


也可以查找前一个窗口,然后向该窗口发送你的自定义消息。你的程序截获这个自定义消息中实现最大化

#11


引用 9 楼 VisualEleven 的回复:
HANDLE hMutex = CreateMutex(NULL, FALSE, _T("XXXXXXXXX"));
if((NULL != hMutex) && (ERROR_ALREADY_EXISTS == GetLastError()))
{
HWND hWnd = ::FindWindow(NULL, _T("XXXXX"));
if(NULL != hWnd)
{
ShowWindow(hWnd, SW_MAXIMIZE);
}
CloseHandle(hMutex);
return FALSE;
}

版主出来果然不一样。用::FindWindow 函数可以。

#12


引用 8 楼 VisualEleven 的回复:
Pid = GetProcessidFromName("are.exe");//根据进程名获得进程ID
        HWND hwnd = NULL;
        hwnd = GetWindowHandleByPID(Pid);//根据进程ID获得窗口句柄
--------------------------
你的这两个得到的HWND句柄对吗?


我发现用上面的方法得到的窗口句柄hwnd 与 用::FindWindow函数得到的窗口句柄不一样,值不一样。是不是存在问题?
我的两个函数代码如下:


//根据进程名获得进程ID
DWORD Casfr::GetProcessidFromName(LPCTSTR name)
{
PROCESSENTRY32 pe;
DWORD id=0;
HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
pe.dwSize=sizeof(PROCESSENTRY32);
if(!Process32First(hSnapshot,&pe))
return 0;
while(1)
{
pe.dwSize=sizeof(PROCESSENTRY32);
if(Process32Next(hSnapshot,&pe)==FALSE)
break;
if(strcmp(pe.szExeFile,name)==0)
{
id=pe.th32ProcessID;

break;
}


}
CloseHandle(hSnapshot);
return id;
}

//通过进程ID获取窗口句柄
HWND Casfr ::GetWindowHandleByPID(DWORD dwProcessID)
{
    HWND h = GetTopWindow(0);
    while ( h )
    {
        DWORD pid = 0;
        DWORD dwTheardId = GetWindowThreadProcessId( h,&pid);

        if (dwTheardId != 0)
        {
            if ( pid == dwProcessID/*your process id*/ )
            {
                // here h is the handle to the window
                return h;
            }
        }

        h = GetNextWindow( h , GW_HWNDNEXT);
    }

    return NULL;
}


请版主及高人帮我看看是不是有问题。

#13


获取进程ID的以后,利用EnumWindows枚举窗口,在枚举窗口的毁掉函数中GetWindowThreadProcessId()比对ID,匹配则找到HWND,返回该HWND窗口句柄即可。

#14


为什么不用互斥量?

#1


HANDLE m_hMutex=CreateMutex(NULL,TRUE,"s1231254353535dd");
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
//AfxMessageBox("该程序已经运行",MB_ICONEXCLAMATION);
ExitProcess(0);
// return FALSE;
}
防止重复打开为什么还要让打开呢?
在BOOL CXXXXApp::InitInstance()加上上面这句好不?直接关闭。。

#2


用线程让前一个程序等待消息,再次打开可以用上段程序判断到,向前一个程序发送消息。。

#3


::ShowWindow(hwnd,SW_SHOWMAXIMIZED);

换成这样试下。
 PostMessage(hWnd, WM_SHOWWINDOW,(WPARAM)TRUE, (LPARAM)SW_OTHERZOOM)

#4


引用 3 楼 zwfgdlc 的回复:
::ShowWindow(hwnd,SW_SHOWMAXIMIZED);

换成这样试下。
 PostMessage(hWnd, WM_SHOWWINDOW,(WPARAM)TRUE, (LPARAM)SW_OTHERZOOM)

谢谢回答,不过消息好像没有传递给hwnd。没有反应。如何让前一个程序响应本程序的消息呢?

#5


引用 2 楼 afairycell 的回复:
用线程让前一个程序等待消息,再次打开可以用上段程序判断到,向前一个程序发送消息。。

谢谢!请问如何让前一个程序等待消息?

#6


引用 1 楼 afairycell 的回复:
HANDLE m_hMutex=CreateMutex(NULL,TRUE,"s1231254353535dd");
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
//AfxMessageBox("该程序已经运行",MB_ICONEXCLAMATION);
ExitProcess(0);
// return FALSE;
}
防止重复打开为什么还要让打开呢?
在BOOL CXXXXApp::InitInstance()加上上面这句好不?直接关闭。。


是把已经打开的那个程序最大化,你上面的给的代码是判断已经打开了程序,直接退出,我是想增加个功能,退出前把已经打开的程序最大化,再退出

#7


把他激活到置顶窗口就行了。

#8


Pid = GetProcessidFromName("are.exe");//根据进程名获得进程ID
        HWND hwnd = NULL;
        hwnd = GetWindowHandleByPID(Pid);//根据进程ID获得窗口句柄
--------------------------
你的这两个得到的HWND句柄对吗?

#9


HANDLE hMutex = CreateMutex(NULL, FALSE, _T("XXXXXXXXX"));
if((NULL != hMutex) && (ERROR_ALREADY_EXISTS == GetLastError()))
{
HWND hWnd = ::FindWindow(NULL, _T("XXXXX"));
if(NULL != hWnd)
{
ShowWindow(hWnd, SW_MAXIMIZE);
}
CloseHandle(hMutex);
return FALSE;
}

#10


也可以查找前一个窗口,然后向该窗口发送你的自定义消息。你的程序截获这个自定义消息中实现最大化

#11


引用 9 楼 VisualEleven 的回复:
HANDLE hMutex = CreateMutex(NULL, FALSE, _T("XXXXXXXXX"));
if((NULL != hMutex) && (ERROR_ALREADY_EXISTS == GetLastError()))
{
HWND hWnd = ::FindWindow(NULL, _T("XXXXX"));
if(NULL != hWnd)
{
ShowWindow(hWnd, SW_MAXIMIZE);
}
CloseHandle(hMutex);
return FALSE;
}

版主出来果然不一样。用::FindWindow 函数可以。

#12


引用 8 楼 VisualEleven 的回复:
Pid = GetProcessidFromName("are.exe");//根据进程名获得进程ID
        HWND hwnd = NULL;
        hwnd = GetWindowHandleByPID(Pid);//根据进程ID获得窗口句柄
--------------------------
你的这两个得到的HWND句柄对吗?


我发现用上面的方法得到的窗口句柄hwnd 与 用::FindWindow函数得到的窗口句柄不一样,值不一样。是不是存在问题?
我的两个函数代码如下:


//根据进程名获得进程ID
DWORD Casfr::GetProcessidFromName(LPCTSTR name)
{
PROCESSENTRY32 pe;
DWORD id=0;
HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
pe.dwSize=sizeof(PROCESSENTRY32);
if(!Process32First(hSnapshot,&pe))
return 0;
while(1)
{
pe.dwSize=sizeof(PROCESSENTRY32);
if(Process32Next(hSnapshot,&pe)==FALSE)
break;
if(strcmp(pe.szExeFile,name)==0)
{
id=pe.th32ProcessID;

break;
}


}
CloseHandle(hSnapshot);
return id;
}

//通过进程ID获取窗口句柄
HWND Casfr ::GetWindowHandleByPID(DWORD dwProcessID)
{
    HWND h = GetTopWindow(0);
    while ( h )
    {
        DWORD pid = 0;
        DWORD dwTheardId = GetWindowThreadProcessId( h,&pid);

        if (dwTheardId != 0)
        {
            if ( pid == dwProcessID/*your process id*/ )
            {
                // here h is the handle to the window
                return h;
            }
        }

        h = GetNextWindow( h , GW_HWNDNEXT);
    }

    return NULL;
}


请版主及高人帮我看看是不是有问题。

#13


获取进程ID的以后,利用EnumWindows枚举窗口,在枚举窗口的毁掉函数中GetWindowThreadProcessId()比对ID,匹配则找到HWND,返回该HWND窗口句柄即可。

#14


为什么不用互斥量?