编程基础 软件工程 JAVA .NET DelphiVisual C/C++ C++Builder Visual Basic C/C++ PowerBuilder 汇编语言 数据结构&算法 破解与加脱壳 移动开发 编程开发技巧与经验
返回首页

VC++通过程序名称找到窗口句柄

时间:2012-11-13来源: 作者: 点击:

//******* Utils.h *******//
#pragma once

 

//////////////////////////////////////////////////////////////////////////
// 类名: Utils
// 工具包类
//////////////////////////////////////////////////////////////////////////
class Utils
{
public:
 // 查找当前是否有指定文件名的进程, 返回0表示未找到
 static DWORD FindProcessByName(CString& strFileName);
 // 根据指定进程ID和参考名字查找主窗口句柄
 static HWND FindWindowByPID( DWORD dwProcessId, CString& strCaption );
 // 杀死指定ID进程
 static BOOL KillProcessByPID( DWORD dwProcessId );
 // 获得硬盘卷序列号(逻辑分区的"软"序列号,每次格式化后都会变!)
 static DWORD GetVolumnSerial( const char cVolumn = 'c' );
 //////////////////////////////////////////////////////////////////////////
 // 说明: 读取Ini配置文件的工具函数
 static void LoadIni( CString& strSection, CString& strKey, INT* pN, CString& strFileName, CString& strDefault = CString("0") );
 static void LoadIni( CString& strSection, CString& strKey, LONG* pL, CString& strFileName, CString& strDefault = CString("0") );
 static void LoadIni( CString& strSection, CString& strKey, FLOAT* pF, CString& strFileName, CString& strDefault = CString("0.0") );
 static void LoadIni( CString& strSection, CString& strKey, CString* pS, CString& strFileName, CString& strDefault = CString("") );
 //////////////////////////////////////////////////////////////////////////

protected:
 // 枚举窗口保存结果的结构
 struct EnumWindowsResultStruct
 {
  BOOL bResult; // [out]返回比较结果
  HWND hWnd;  // [out]枚举的窗口句柄
  DWORD dwProcId; // [in]要和当前窗口进程ID比较的目标进程ID
  CString strCaption; // [in]窗口标题参考文字

  EnumWindowsResultStruct()
  {
   bResult  = FALSE; // [out]返回比较结果
   hWnd  = NULL;  // [out]枚举的窗口句柄
   dwProcId = 0;  // [in]要和当前窗口进程ID比较的目标进程ID
  }

  void Init(void)
  {
   bResult  = FALSE; // [out]返回比较结果
   hWnd  = NULL;  // [out]枚举的窗口句柄
   dwProcId = 0;  // [in]要和当前窗口进程ID比较的目标进程ID
   strCaption.Empty();
  }
 };

 // 遍历窗口回调函数
 static BOOL CALLBACK EnumProc(HWND hWnd, LPARAM lParam);
 // 枚举用虚函数
 static BOOL OnEnumProc(HWND hWnd, EnumWindowsResultStruct* pewrsInOut);
};

 


//******* Utils.cpp *******//

 

#include "stdafx.h"
#include <atlbase.h>
#include <atlwin.h>
#include "Utils.h"
#include <tlhelp32.h>

//////////////////////////////////////////////////////////////////////////
// 命名空间: Utils
// 工具包
//////////////////////////////////////////////////////////////////////////
// 查找当前是否有指定文件名的进程
DWORD Utils::FindProcessByName(CString& strFileName)
{
 HANDLE   hProcSnap = NULL; // 进程快照句柄
 PROCESSENTRY32 pe32  = {0}; // 系统信息

 // 创建系统快照
 hProcSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
 if( hProcSnap == INVALID_HANDLE_VALUE )
  return FALSE;

 // 在使用PROCESSENTRY32结构前必须填充尺寸
 pe32.dwSize = sizeof(PROCESSENTRY32);

 // 遍历进程快照, 查找指定文件名
 if( Process32First( hProcSnap, &pe32 ) )
 {
  do
  {

   // 比较进程名字和传进来的文件名
   CString strExe( pe32.szExeFile );
   //LogFormatedMsg( "C:\\list.txt", "%s", strExe ); // debug code
   DWORD dwProcessID = pe32.th32ProcessID; // 遍历列表的进程ID

   // 有相同名字的进程, 并且不同于当前程序ID, 才是前一个运行中的实例
   if( strExe.CompareNoCase( strFileName ) == 0
    && dwProcessID != GetCurrentProcessId() )
    return dwProcessID;
  }
  while( Process32Next( hProcSnap, &pe32 ) );
 }

 // 退出前要清理快照对象
 CloseHandle( hProcSnap );
 return FALSE;
}

// 根据指定进程ID查找主窗口句柄
HWND Utils::FindWindowByPID( DWORD dwProcessId, CString& strCaption )
{
 //LogFormatedMsg( "C:\\list.txt", "目标进程ID: %l", dwProcessId );

 // EnumWindows是自动重复回调的, 外面不用循环了
 EnumWindowsResultStruct ewrsProc;
 ewrsProc.dwProcId = dwProcessId; // 比较的目标进程ID
 ewrsProc.strCaption = strCaption; // 比较的目标窗口名称

 //------------------------------------------------
 // EnumWindows找到窗口(枚举)时, 就会返回非0值;
 // 回调函数里因为返回是BOOL, 找到窗口会返回FALSE
 // , 而枚举完毕也会返回FALSE。所以我们处理当返回
 // FALSE时候, 判断结构里面的比较值和窗口句柄是否
 // 有效来区分是枚举完毕还是找到窗口。
 //------------------------------------------------
 if( !EnumWindows(EnumProc, (LPARAM)&ewrsProc) )
 {
  // 这里只是正确枚举到了一个窗口, 还需要根据枚举结果来判断
  if( ewrsProc.bResult && ewrsProc.hWnd )
  {
   // 这里才是真正比较到了正确的进程ID
   return ewrsProc.hWnd;
  }
 }

 return NULL;
}

// 杀死指定ID进程
BOOL Utils::KillProcessByPID( DWORD dwProcessId )
{
 BOOL bRet = FALSE;
 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessId );
 if( hProcess )
 {
  bRet = TerminateProcess( hProcess, 0 );
 }
 CloseHandle( hProcess );

 return bRet;
}

// 获得硬盘卷序列号(逻辑分区的"软"序列号,每次格式化后都会变!)
DWORD Utils::GetVolumnSerial( const char cVolumn )
{
 // 合成卷标
 CString strVolume;
 strVolume.Format( "%c:\", toupper(cVolumn) );
 DWORD dwSerial = 0;
 TCHAR szName[MAX_PATH];
 GetVolumeInformation( strVolume, szName, MAX_PATH, &dwSerial, NULL, NULL, NULL, NULL );
 return dwSerial;
}

// 遍历窗口回调函数
BOOL CALLBACK Utils::EnumProc(HWND hWnd, LPARAM lParam)
{
 ////return ((Utils*)lp)->OnEnumProc(hWnd);

 // 通过结构来传递所需的结果和数据, 所以直接返回就可以了
 return OnEnumProc( hWnd, (EnumWindowsResultStruct*)lParam );
}

// 枚举用虚函数
BOOL Utils::OnEnumProc(HWND hWnd, EnumWindowsResultStruct* pewrsInOut)
{
 if( hWnd )
 {
  // 每次都先清空这两个输出值, 让外面能判断是枚举完了还是找到进程了(都返回FALSE)
  pewrsInOut->bResult = FALSE;
  pewrsInOut->hWnd = NULL;

  DWORD dwProcId, dwThreadId;
  // 返回的是线程ThreadID,参数里获得的才是进程ProcessID
  dwThreadId = GetWindowThreadProcessId( hWnd, &dwProcId );

  //// DebugCode
  //TCHAR szTemp[MAX_PATH];
  //GetWindowText( hWnd, szTemp, MAX_PATH );
  //LogFormatedMsg( "C:\\list.txt", "Thr: %l|Prc: %l \t"%s" -->HWND: %l", dwThreadId, dwProcId, szTemp, hWnd ); // debug code

  // 处理比较结果成功的清空
  if( dwProcId == pewrsInOut->dwProcId )
  {
   // 一个进程会有N多窗口...只好尝试取第一个有标题的认为是主窗口了
   TCHAR szBuff[MAX_PATH];
   int nTitleLen = GetWindowText( hWnd, szBuff, MAX_PATH );
   // 窗口没标题的就不理了
   if( nTitleLen > 0 )
   {
    CString strBuff(szBuff);
    LPTSTR szCaption = pewrsInOut->strCaption.GetBuffer();
    int iPos = strBuff.Find( szCaption );
    pewrsInOut->strCaption.ReleaseBuffer();

    // 再比较窗口标题和传入的参考文字
    if( iPos != -1 )
    {
     pewrsInOut->bResult = TRUE;
     pewrsInOut->hWnd = hWnd; // 传出去窗口句柄
     return FALSE; // 默认成功TRUE会一直循环回调...只有用FALSE来完结了
    }
   }
  }
 }

 return TRUE;
}


// 说明: 读取Ini配置文件的工具函数
void Utils::LoadIni( CString& strSection, CString& strKey, INT* pN, CString& strFileName, CString& strDefault )
{
 char pStr[MAX_PATH];
 GetPrivateProfileStringA( strSection, strKey, strDefault, pStr, MAX_PATH, strFileName );
 *pN = atoi( pStr );
}

void Utils::LoadIni( CString& strSection, CString& strKey, LONG* pL, CString& strFileName, CString& strDefault )
{
 char pStr[MAX_PATH];
 GetPrivateProfileStringA( strSection, strKey, strDefault, pStr, MAX_PATH, strFileName );
 *pL = atol( pStr );
}

void Utils::LoadIni( CString& strSection, CString& strKey, FLOAT* pF, CString& strFileName, CString& strDefault )
{
 char pStr[MAX_PATH];
 GetPrivateProfileStringA( strSection, strKey, strDefault, pStr, MAX_PATH, strFileName );
 DOUBLE temp = atof( pStr );
 *pF = (FLOAT)temp;
}

void Utils::LoadIni( CString& strSection, CString& strKey, CString* pS, CString& strFileName, CString& strDefault )
{
 char pStr[MAX_PATH];
 GetPrivateProfileStringA( strSection, strKey, strDefault, pStr, MAX_PATH, strFileName );
 *pS = pStr;
}

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
验证码:点击我更换图片
推荐内容