C++ 从进程名称获取窗口标题
我试图写一个程序,可以得到一个进程的窗口标题。 在我描述问题之前,以下是代码:C++ 从进程名称获取窗口标题,c++,winapi,C++,Winapi,我试图写一个程序,可以得到一个进程的窗口标题。 在我描述问题之前,以下是代码: #include <Windows.h> #include <string> #include <Psapi.h> #include <algorithm> std::string window_title; std::string search_for; BOOL CALLBACK EnumWindowCallback(HWND hWindow, LPAR
#include <Windows.h>
#include <string>
#include <Psapi.h>
#include <algorithm>
std::string window_title;
std::string search_for;
BOOL CALLBACK EnumWindowCallback(HWND hWindow, LPARAM param)
{
if ( IsWindow( hWindow ) == TRUE )
{
DWORD pid = 0;
if ( GetWindowThreadProcessId( hWindow, &pid ) != 0 )
{
HANDLE hProcess;
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
if ( hProcess != 0 )
{
std::string path;
CHAR name[MAX_PATH];
GetModuleFileNameExA( hProcess, NULL, name, sizeof(name) / sizeof(CHAR) );
path = name;
unsigned int slash = path.find_last_of('\\');
if ( slash != std::string::npos ){
std::string proc_name = path.substr( slash + 1, path.length() );
std::transform(proc_name.begin(), proc_name.end(), proc_name.begin(), ::tolower);
if ( proc_name == search_for )
{
CHAR finalTitle[MAX_PATH];
ZeroMemory( finalTitle, sizeof(finalTitle) );
SendMessageA( hWindow, WM_GETTEXT, (WPARAM)sizeof(CHAR)/sizeof(MAX_PATH), (LPARAM)finalTitle );
window_title = finalTitle;
return FALSE;
}
}
}
}
}
return TRUE;
};
const char* __stdcall GetWinTitleByProcessName( const char* title )
{
search_for = title;
std::transform(search_for.begin(), search_for.end(), search_for.begin(), ::tolower);
if ( EnumWindows( (WNDENUMPROC)EnumWindowCallback, 0 ) == FALSE )
{
return window_title.c_str();
}
return "NOTFOUND";
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
MessageBoxA( NULL, GetWinTitleByProcessName("chrome.exe"), "Test", MB_OK);
}
#包括
#包括
#包括
#包括
字符串窗口标题;
std::字符串搜索;
BOOL回调EnumWindowCallback(HWND hWindow,LPARAM参数)
{
如果(IsWindow(hWindow)==TRUE)
{
DWORD pid=0;
如果(GetWindowThreadProcessId(hWindow和pid)!=0)
{
处理hProcess;
hProcess=OpenProcess(PROCESS\u ALL\u ACCESS,FALSE,pid);
如果(HPProcess!=0)
{
std::字符串路径;
字符名称[最大路径];
GetModuleFileNameExA(hProcess,NULL,name,sizeof(name)/sizeof(CHAR));
路径=名称;
unsigned int slash=path.find_last_of('\\');
if(斜杠!=std::string::npos){
string proc_name=path.substr(斜杠+1,path.length());
std::transform(proc_name.begin(),proc_name.end(),proc_name.begin(),::tolower);
if(proc_name==搜索)
{
CHAR finalTitle[MAX_PATH];
零内存(finalTitle,sizeof(finalTitle));
sendmagesa(hWindow,WM_GETTEXT,(WPARAM)sizeof(CHAR)/sizeof(MAX_PATH),(LPARAM)finalTitle);
窗口标题=最终标题;
返回FALSE;
}
}
}
}
}
返回TRUE;
};
常量字符*\uu stdcall GetWinTitleByProcessName(常量字符*标题)
{
搜索=标题;
std::transform(搜索.begin()、搜索.end()、搜索.begin()、::tolower);
if(EnumWindows((WNDENUMPROC)EnumWindowCallback,0)=FALSE)
{
返回窗口_title.c_str();
}
返回“NOTFOUND”;
}
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
MessageBoxA(NULL,GetWinTitleByProcessName(“chrome.exe”),“Test”,MB_OK);
}
到目前为止,这个程序一直在运行,直到我想得到窗口的实际标题为止。
我尝试了GetWindowText和SendMessage,如下所示。
这两个方法都返回空字符串
如何获取窗口标题?似乎(WPARAM)sizeof(CHAR)/sizeof(MAX_PATH)会返回零,因为sizeof(CHAR)会防御性地小于MAX PATH,所以您对WinAPI说您的变量长度为零,这就是为什么它会向您返回空字符串。
改为指定最大路径值。以下代码适用于类似问题。在我的例子中,我正在寻找应用程序的windows句柄,这样我就可以创建dll的父级。我通过标题识别应用程序。它的C++Builder代码,因此某些部分可能不熟悉。我将评论我发现的差异。主要是应用程序的使用,我不确定非Embarcadero的等价物是什么,但是每个正在运行的代码实例都有一个管理消息循环的应用程序实例,等等。我将dll的Application->Handle设置为调用apps的hWnd,以使其远离任务栏。此代码适用于xp、vista 32和win7 64
void HideDLL() {
if (Application->Handle == 0) {
SearchObject *so = new SearchObject();
so->Caption = L"MyCallingApp";
so->Handle = 0;
EnumWindows((WNDENUMPROC)EnumWindowsProc, (long)so);
Application->Handle = so->Handle;
delete so;
}
}
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lparam) {
bool result;
SearchObject *so = (SearchObject*)lparam;
wchar_t *caption = new wchar_t[STR_DEFAULT];
GetWindowTextW(hWnd, caption, STR_DEFAULT);
// String is an Embarcadero type representing UnicodeString
String Caption = caption;
// Pos is a wrapper around strstr I think
// the actual caption in my case is decorated with some other stuff
// I only know that it will start with the name of the app
if (Caption.Pos(so->Caption) > 0) {
so->Handle = hWnd;
result = false;
} else {
result = true;
}
delete caption;
return result;
}
希望这能有所帮助。我已经访问了这个问题:但它并没有真正包含一个满足我问题的解决方案。您为什么使用ANSI字符串而不是Unicode字符串,这也是非混合业务吗?今年是2013年,所有Windows程序都应该完全采用Unicode。将
char
和sendmagesa
替换为wchar\u t
和sendmagesw
。确保为您的项目定义了UNICODE
符号。因为最终结果需要为char,因为它被导出到一种不理解wchar\u t的古老脚本语言。如果在使用CreateWindowW
创建的窗口上调用sendmagesa
,则调用可能会失败。调用并使用适当的SendMessageA
/W
变量。@Tim窗口的字符集由RegisterClass
函数决定,而不是CreateWindow
。我不能肯定,但我非常确定系统能够无缝地处理窗口消息的翻译,因此sendmages
的任何一种变体都可以工作。基本上,IsWindowUnicode
是在内部调用的。