MFC通过wininet下载文件

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保存成图片

把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;
}

HPSocket中SendSmallFile的使用

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控件

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遍历窗口

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();
}

WIN32 主线程中不能使用 WaitForSingleObject

主线程中不能使用 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获取当前程序所在目录

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);