VC模拟鼠标点击
SetCursorPos(472, 356);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(1000);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
VC模拟鼠标点击
SetCursorPos(472, 356);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(1000);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
VS2013 VC中添加自定义资源:
先添加自定义类型,然后再打开添加资源对话框,点导入,导入的时候选刚才添加的资源类型即可。
MFC通过wininet下载文件
// down.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include <windows.h>
#include <wininet.h>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
#pragma comment(lib, "wininet.lib")
//下载
#define DOWNHELPER_AGENTNAME "down"
#define LEN_OF_BUFFER_FOR_QUERYINFO 128
#define DOWNLOAD_BUF_SIZE (10*1024) //10KB
#define MAX_DOWNLOAD_REQUEST_TIME 10
#define MAX_DOWNLOAD_BYTESIZE (1000*1024*1024) //1000MB
BOOL _TryHttpSendRequest(LPVOID hRequest, int nMaxTryTimes); //多次发送请求函数
//HTTP下载函数,通过先请求HEAD的方式然后GET,可以通过HEAD对下载的文件类型和大小做限制
BOOL DownloadUrl(std::string strUrl, std::string strFileName)
{
BOOL bRet = FALSE;
if (strUrl == "" || strFileName == "")
return FALSE;
//定义变量
HINTERNET hInet = NULL; //打开internet连接handle
HINTERNET hConnect = NULL; //HTTP连接
HINTERNET hRequestHead = NULL; //HTTP Request
HINTERNET hRequestGet = NULL; //HTTP Request
HANDLE hFileWrite = NULL; //写文件的句柄
char* pBuf = NULL; //缓冲区
DWORD dwRequestTryTimes = MAX_DOWNLOAD_REQUEST_TIME; //尝试请求的次数
DWORD dwDownBytes = 0; //每次下载的大小
DWORD dwDownFileTotalBytes = 0; //下载的文件总大小
DWORD dwWriteBytes = 0; //写入文件的大小
char bufQueryInfo[LEN_OF_BUFFER_FOR_QUERYINFO] = {0}; //用来查询信息的buffer
DWORD dwBufQueryInfoSize = sizeof(bufQueryInfo);
DWORD dwStatusCode = 0;
DWORD dwContentLen = 0;
DWORD dwSizeDW = sizeof(DWORD);
//分割URL
CHAR pszHostName[INTERNET_MAX_HOST_NAME_LENGTH] = {0};
CHAR pszUserName[INTERNET_MAX_USER_NAME_LENGTH] = {0};
CHAR pszPassword[INTERNET_MAX_PASSWORD_LENGTH] = {0};
CHAR pszURLPath[INTERNET_MAX_URL_LENGTH] = {0};
CHAR szURL[INTERNET_MAX_URL_LENGTH] = {0};
URL_COMPONENTSA urlComponents = {0};
urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
urlComponents.lpszHostName = pszHostName;
urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
urlComponents.lpszUserName = pszUserName;
urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
urlComponents.lpszPassword = pszPassword;
urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
urlComponents.lpszUrlPath = pszURLPath;
urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
bRet = InternetCrackUrlA(strUrl.c_str(), 0, NULL, &urlComponents);
bRet = (bRet && urlComponents.nScheme == INTERNET_SERVICE_HTTP);
if (!bRet)
{
goto _END_OF_DOWNLOADURL;
}
//打开一个internet连接
hInet = InternetOpenA(DOWNHELPER_AGENTNAME, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL);
if (!hInet)
{
bRet = FALSE;
goto _END_OF_DOWNLOADURL;
}
//打开HTTP连接
hConnect = InternetConnectA(hInet, pszHostName, urlComponents.nPort, pszUserName, pszPassword, INTERNET_SERVICE_HTTP, 0, NULL);
if (!hConnect)
{
bRet = FALSE;
goto _END_OF_DOWNLOADURL;
}
//创建HTTP request句柄
if (urlComponents.dwUrlPathLength != 0)
strcpy(szURL, urlComponents.lpszUrlPath);
else
strcpy(szURL, "/");
//请求HEAD,通过HEAD获得文件大小及类型进行校验
hRequestHead = HttpOpenRequestA(hConnect, "HEAD", szURL, "HTTP/1.1", "", NULL, INTERNET_FLAG_RELOAD, 0);
bRet = _TryHttpSendRequest(hRequestHead, dwRequestTryTimes);
if (!bRet)
{
goto _END_OF_DOWNLOADURL; //请求HEAD失败
}
//查询content-length大小
dwContentLen = 0;
dwSizeDW = sizeof(DWORD);
bRet = HttpQueryInfo(hRequestHead, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_CONTENT_LENGTH, &dwContentLen, &dwSizeDW, NULL);
if (bRet)
{
//检查是否文件过大
if (dwContentLen > MAX_DOWNLOAD_BYTESIZE)
{
bRet = FALSE;
goto _END_OF_DOWNLOADURL;
}
}
//校验完成后再请求GET,下载文件
hRequestGet = HttpOpenRequestA(hConnect, "GET", szURL, "HTTP/1.1", "", NULL, INTERNET_FLAG_RELOAD, 0);
bRet = _TryHttpSendRequest(hRequestGet, dwRequestTryTimes);
if (!bRet)
{
goto _END_OF_DOWNLOADURL; //请求HEAD失败
}
//创建文件
hFileWrite = CreateFileA(strFileName.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFileWrite)
{
bRet = FALSE;
goto _END_OF_DOWNLOADURL;
}
//分配缓冲
pBuf = new char[DOWNLOAD_BUF_SIZE]; //分配内存
if (!pBuf)
{
bRet = FALSE;
goto _END_OF_DOWNLOADURL;
}
//多次尝试下载文件
dwDownFileTotalBytes = 0;
while (1)
{
dwDownBytes = 0;
memset(pBuf, 0, DOWNLOAD_BUF_SIZE*sizeof(char));
bRet = InternetReadFile(hRequestGet, pBuf, DOWNLOAD_BUF_SIZE, &dwDownBytes);
if (bRet)
{
if (dwDownBytes > 0)
{
dwDownFileTotalBytes += dwDownBytes;
bRet = WriteFile(hFileWrite, pBuf, dwDownBytes, &dwWriteBytes, NULL); //写入文件
if (!bRet)
{
goto _END_OF_DOWNLOADURL;
}
}
else if (0 == dwDownBytes)
{
bRet = TRUE;
break; //下载成功完成
}
}
}
//清理
_END_OF_DOWNLOADURL:
if (INVALID_HANDLE_VALUE != hFileWrite)
CloseHandle(hFileWrite);
if (pBuf)
delete [] pBuf;
if (hRequestGet)
InternetCloseHandle(hRequestGet);
if (hRequestHead)
InternetCloseHandle(hRequestHead);
if (hConnect)
InternetCloseHandle(hConnect);
if (hInet)
InternetCloseHandle(hInet);
return bRet;
}
//多次发送请求函数
BOOL _TryHttpSendRequest(LPVOID hRequest, int nMaxTryTimes)
{
BOOL bRet = FALSE;
DWORD dwStatusCode = 0;
DWORD dwSizeDW = sizeof(DWORD);
while (hRequest && (nMaxTryTimes-- > 0)) //多次尝试发送请求
{
//发送请求
bRet = HttpSendRequestA(hRequest, NULL, 0, NULL, 0);
if (!bRet)
{
continue;
}
else
{
//判断HTTP返回的状态码
dwStatusCode = 0;
dwSizeDW = sizeof(DWORD);
bRet = HttpQueryInfo(hRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE, &dwStatusCode, &dwSizeDW, NULL);
if (bRet)
{
//检查状态码
if (HTTP_STATUS_OK == dwStatusCode) //200 OK
{
break;
}
else
{
bRet = FALSE;
continue;
}
}
}
}
return bRet;
}
//////////////////////////////////////////////////////////////////////////
BOOL HttpGet(string url, string &result)
{
vector<char> v;
const CHAR * szUrl = url.c_str();
CHAR szAgent[] = "";
HINTERNET hInternet1 =
InternetOpen(NULL,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,NULL);
if (NULL == hInternet1)
{
InternetCloseHandle(hInternet1);
return FALSE;
}
HINTERNET hInternet2 =
InternetOpenUrl(hInternet1,szUrl,NULL,NULL,INTERNET_FLAG_NO_CACHE_WRITE,NULL);
if (NULL == hInternet2)
{
InternetCloseHandle(hInternet2);
InternetCloseHandle(hInternet1);
return FALSE;
}
DWORD dwMaxDataLength = 500;
PBYTE pBuf = (PBYTE)malloc(dwMaxDataLength*sizeof(TCHAR));
if (NULL == pBuf)
{
InternetCloseHandle(hInternet2);
InternetCloseHandle(hInternet1);
return FALSE;
}
DWORD dwReadDataLength = NULL;
BOOL bRet = TRUE;
do
{
ZeroMemory(pBuf,dwMaxDataLength*sizeof(TCHAR));
bRet = InternetReadFile(hInternet2,pBuf,dwMaxDataLength,&dwReadDataLength);
for (DWORD dw = 0;dw < dwReadDataLength;dw++)
{
v.push_back(pBuf[dw]);
}
} while (NULL != dwReadDataLength);
vector<char>::iterator i;
for(i=v.begin(); i!=v.end(); i++)
result += *i;
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
/*
int main(int argc, char* argv[])
{
cout << "正在下载...";
BOOL bR = DownloadUrl("http://42.duote.com.cn/office2007.zip", "test.zip");
if (bR)
cout << "完成" << endl;
else
cout << "失败" << endl;
return 0;
}
*/
string trim(const string& str)
{
string::size_type pos = str.find_first_not_of(' ');
if (pos == string::npos)
{
return str;
}
string::size_type pos2 = str.find_last_not_of(' ');
if (pos2 != string::npos)
{
return str.substr(pos, pos2 - pos + 1);
}
return str.substr(pos);
}
int split(const string& str, vector<string>& ret_, string sep = ",")
{
if (str.empty())
{
return 0;
}
string tmp;
string::size_type pos_begin = str.find_first_not_of(sep);
string::size_type comma_pos = 0;
while (pos_begin != string::npos)
{
comma_pos = str.find(sep, pos_begin);
if (comma_pos != string::npos)
{
tmp = str.substr(pos_begin, comma_pos - pos_begin);
pos_begin = comma_pos + sep.length();
}
else
{
tmp = str.substr(pos_begin);
pos_begin = comma_pos;
}
if (!tmp.empty())
{
ret_.push_back(tmp);
tmp = "";
}
}
return 0;
}
string replace(const string& str, const string& src, const string& dest)
{
string ret;
string::size_type pos_begin = 0;
string::size_type pos = str.find(src);
while (pos != string::npos)
{
cout <<"replacexxx:" << pos_begin <<" " << pos <<"\n";
ret.append(str.data() + pos_begin, pos - pos_begin);
ret += dest;
pos_begin = pos + 1;
pos = str.find(src, pos_begin);
}
if (pos_begin < str.length())
{
ret.append(str.begin() + pos_begin, str.end());
}
return ret;
}
void Debug(string str)
{
MessageBox(NULL, str.c_str(), "DEBUG", MB_OK);
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
string html;
if (!HttpGet("http://42.96.190.81:81/list.txt", html))
{
MessageBox(NULL, "列表获取失败!", "ERROR", MB_OK);
return 0;
}
vector<string> urls;
split(html, urls, "\r\n");
for(int i=0; i<urls.size(); i++)
{
size_t pos = urls[i].rfind('/', urls[i].size());
string fileName = urls[i].substr(pos+1, urls[i].size()-pos-1);
if (DownloadUrl(urls[i], fileName))
{
Debug(fileName + "下载成功");
}
}
Debug("完成");
return 0;
}
把HDC保存成图片,做法如下:
先调用CopyDCToBitmap
把HDC转成HBITMAP, 然后调用 SaveBmp
或SaveImg
BOOL SaveBmp (HBITMAP hBitmap, CString FileName)
{
HDC hDC;
//当前分辨率下每象素所占字节数
int iBits;
//位图中每象素所占字节数
WORD wBitCount;
//定义调色板大小,位图中像素字节大小,位图文件大小,写入文件字节数
DWORD dwPaletteSize = 0, dwBmBitsSize = 0, dwDIBSize = 0, dwWritten = 0;
//位图属性结构
BITMAP Bitmap;
//位图文件头结构
BITMAPFILEHEADER bmfHdr;
//位图信息头结构
BITMAPINFOHEADER bi;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
//定义文件,分配内存句柄,调色板句柄
HANDLE fh, hDib, hPal, hOldPal = NULL;
//计算位图文件每个像素所占字节数
hDC = CreateDC(_T("DISPLAY"), NULL, NULL , NULL);
iBits = GetDeviceCaps( hDC, BITSPIXEL) * GetDeviceCaps (hDC , PLANES);
DeleteDC( hDC);
if (iBits <= 1) wBitCount = 1;
else if (iBits <= 4) wBitCount = 4;
else if (iBits <= 8) wBitCount = 8;
else wBitCount = 24;
GetObject(hBitmap, sizeof(Bitmap), (LPSTR)& Bitmap);
bi.biSize = sizeof( BITMAPINFOHEADER);
bi.biWidth = Bitmap. bmWidth;
bi.biHeight = Bitmap. bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
dwBmBitsSize = (( Bitmap. bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
// 为位图内容分配内存
hDib = GlobalAlloc( GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER ));
lpbi = (LPBITMAPINFOHEADER) GlobalLock(hDib );
*lpbi = bi;
// 处理调色板
hPal = GetStockObject( DEFAULT_PALETTE);
if (hPal)
{
hDC = :: GetDC( NULL);
//hDC = m_pDc->GetSafeHdc();
hOldPal = :: SelectPalette(hDC , (HPALETTE)hPal, FALSE);
RealizePalette(hDC );
}
// 获取该调色板下新的像素值
GetDIBits( hDC, hBitmap, 0, ( UINT)Bitmap .bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER )
+ dwPaletteSize, (BITMAPINFO *)lpbi , DIB_RGB_COLORS);
// 恢复调色板
if (hOldPal)
{
:: SelectPalette(hDC , (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC );
:: ReleaseDC(NULL , hDC );
}
// 创建位图文件
fh = CreateFile( FileName, GENERIC_WRITE, 0, NULL , CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN , NULL);
if (fh == INVALID_HANDLE_VALUE)
return FALSE;
// 设置位图文件头
bmfHdr.bfType = 0x4D42; // ;BM;
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof( BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize ;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = ( DWORD)sizeof (BITMAPFILEHEADER) + (DWORD)sizeof (BITMAPINFOHEADER) + dwPaletteSize;
// 写入位图文件头
WriteFile( fh, ( LPSTR)&bmfHdr , sizeof (BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile( fh, ( LPSTR)lpbi , dwDIBSize , &dwWritten , NULL);
// 清除
GlobalUnlock( hDib);
GlobalFree( hDib);
CloseHandle( fh);
return TRUE;
}
// 保存成JPG文件
BOOL SaveImg (HBITMAP hBitmap, CString imgFile)
{
BITMAP bm;
int width, height;
GetObject(hBitmap, sizeof(BITMAP), & bm);
width = bm.bmWidth;
height = bm.bmHeight;
CDC memDC;
memDC.CreateCompatibleDC( NULL);
memDC.SelectObject(hBitmap);
CImage image;
image.Create(width, height, 32);
BitBlt( image. GetDC(), 0, 0, width, height, memDC. m_hDC, 0, 0, SRCCOPY );
HRESULT hResult = image. Save(imgFile );
//image.Save(_T("new.bmp"), Gdiplus::ImageFormatBMP); // 保存成bmp
image.ReleaseDC();
memDC.DeleteDC();
return SUCCEEDED( hResult);
}
HBITMAP CopyDCToBitmap (HDC hScrDC, LPRECT lpRect)
{
HDC hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;
// 位图宽度和高度
// 确保选定区域不为空矩形
if (IsRectEmpty( lpRect))
return NULL;
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC( hScrDC);
// 创建一个与屏幕设备描述表兼容的位图,函数需要与CreateCompatibleDC配合使用
hBitmap = CreateCompatibleBitmap( hScrDC, nWidth, nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap = ( HBITMAP)SelectObject (hMemDC , hBitmap );
// 把屏幕设备描述表拷贝到内存设备描述表中
// StretchBlt函数从源矩形中复制一个位图到目标矩形,必要时按目前目标设备设置的模式进行图像的拉伸或压缩。
StretchBlt( hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, nWidth, nHeight, SRCCOPY); // SRCCOPY
//BitBlt(hMemDC, 0, 0, nWidth, nHeight,hScrDC, nX, nY, SRCCOPY);
// 得到屏幕位图的句柄
hBitmap = (HBITMAP) SelectObject(hMemDC , hOldBitmap );
// 清除
//DeleteDC(hScrDC);
DeleteDC( hMemDC);
DeleteObject( hOldBitmap);
// 返回位图句柄
return hBitmap;
}
HP–Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,这里记录的是通过 HP–Socket 发送小文件的功能,代码如下:
p-> GetCurrentImage();
CFile file (_T("$shs.jpg"), CFile::modeRead );
auto uLen = file. GetLength();
file. Close();
TPkgHeader * header = new TPkgHeader ();
header-> seq = NET_SSH_SCREEN;
header-> body_len = uLen;
WSABUF buf ;
buf. len = sizeof (TPkgHeader );
buf. buf = (CHAR *)header ;
p-> m_pSocket-> GetTcpPullClientPtr()->SendSmallFile (_T("$shs.jpg"), &buf, NULL );
VC跨进程操作SysListview32控件,代码如下:
bool CTaskManager::StockCodeIsExist(CString stockCode)
{
HWND hMain = CWndHelper::GetMainWnd();
HWND hListview = ::FindWindowEx(hMain, NULL, _T("SysListView32"), NULL);
ASSERT(hListview);
//listview的列头句柄
int headerhwnd = ::SendMessage(hListview, LVM_GETHEADER, 0, 0);
//总行数
int rows = ::SendMessage(hListview, LVM_GETITEMCOUNT, 0, 0);
//列表列数
int cols = ::SendMessage((HWND)headerhwnd, HDM_GETITEMCOUNT, 0, 0);
DWORD ProcessID = NULL;
DWORD ThreadID = GetWindowThreadProcessId(hListview, &ProcessID);
//打开并插入进程
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, ProcessID);
//申请代码的内存区
LPVOID pointer = (LVITEM*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
bool result = false;
for (int i = 0; i < rows; i++)
{
int j = 0;
// for (int j = 0; j < cols; j++)
{
LVITEM vItem;
vItem.mask = LVIF_TEXT; //说明pszText是有效的
vItem.iItem = i; //行号
vItem.iSubItem = j; //列号
vItem.cchTextMax = 512; //所能存储的最大的文本为256字节
LPWSTR pItem = NULL;
//申请内存空间
pItem = (LPWSTR)VirtualAllocEx(hProcess, NULL, 512, MEM_COMMIT, PAGE_READWRITE);
vItem.pszText = pItem;
WriteProcessMemory(hProcess, pointer, &vItem, sizeof(LVITEM), NULL);
::SendMessage(hListview, LVM_GETITEMW, (WPARAM)i, (LPARAM)pointer);
char ItemBuf[512];
memset(ItemBuf, 0, 512);
ReadProcessMemory(hProcess, pItem, ItemBuf, 512, NULL);
CString strItemText; //i行j列的文本值
strItemText.Format(_T("%s"), ItemBuf);
if (strItemText == stockCode)
{
//选中行
vItem.state = LVIS_SELECTED | LVIS_FOCUSED | LVIS_ACTIVATING;
vItem.stateMask = LVIS_SELECTED;
WriteProcessMemory(hProcess, pointer, &vItem, sizeof(LVITEM), NULL);
SendMessage(hListview, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)pointer);
result = true;
}
//释放内存空间
VirtualFreeEx(hProcess, pItem, 0, MEM_RELEASE);
}
}
//释放内存空间
VirtualFreeEx(hProcess, pointer, 0, MEM_RELEASE);//在其它进程中释放申请的虚拟内存空间,MEM_RELEASE方式很彻底,完全回收
CloseHandle(hProcess);//关闭打开的进程对象
return result;
}
EnumWindows遍历窗口
#include <vector>
using namespace std;
vector<HWND > m_hWnds;
BOOL EnumWindowsProc(HWND hWnd , LPARAM lParam )
{
if (::GetWindowLong( hWnd, GWL_STYLE)& WS_VISIBLE)
{
char szClassName[128] = { 0 };
if (::GetClassNameA( hWnd, szClassName, 128) != 0)
{
if (strcmp( "3DSMAX", szClassName) == 0)
{
m_hWnds.push_back( hWnd);
}
}
}
return TRUE;
}
int Get3dmaxWndCount()
{
m_hWnds.clear();
::EnumWindows((WNDENUMPROC)EnumWindowsProc, NULL);
return (int)m_hWnds.size();
}
主线程中不能使用 WaitForSingleObject(m_GameProcessInfo.hProcess, INFINITE);
这样会造成莫名奇妙的问题,比如我在一个项目这样用了,结果客户反馈说程序会造成鼠标一在转圈圈。经远程远程客户机排查,结果就是在主线程中使用WaitForSingleObject(m_GameProcessInfo.hProcess, INFINITE); 导致了主线程消息循环阻塞而引发的。
经过在网上查找,很快找到了解决方案,用下面的代码取代WaitForSingleObject.
while (TRUE)
{
DWORD result;
MSG msg;
result = MsgWaitForMultipleObjects(1, &m_GameProcessInfo.hProcess,
FALSE, INFINITE, QS_ALLINPUT);
if (result == ( WAIT_OBJECT_0))
{
break;
}
else
{
PeekMessage(&msg, NULL , 0, 0, PM_REMOVE );
DispatchMessage(&msg);
}
}
微软对此函数的解释是:
为了解决在主线程中Wait的问题,微软专门设计了一个函数MsgWaitForMultipleObjects,这个函数即可以等待信号(thread,event,mutex等等),也可以等待消息(MSG)。即不论有信号被激发或者有消息到来,此函数都可以返回。
这样改过后,再发给客户测试,现象消失,问题解决。
WIN32获取当前程序所在目录
#include <Shlwapi.h>
#pragma comment (lib , "shlwapi.lib" )
TCHAR wszModulePath[MAX_PATH ];
::memset(wszModulePath, 0, sizeof(TCHAR)*MAX_PATH);
GetModuleFileName(NULL , wszModulePath, MAX_PATH);
PathAppend(wszModulePath, _T ("..\\" ));
wcscat_s(wszModulePath, GAME_CLIENT_PATH);
AfxBeginThread
是MFC封装的函数,返回的是CWinThread*
,不能用于CloseHandle
。AfxBeginThread
在线程执行完后会句柄资源自动释放。
如果是::CreateThread
创建的线程则要手工调用CloseHandle
释放线程句柄。