标签: mfc

  • MFC 打印图片

    MFC 实现打印图片功能,代码如下:

    BOOL PrintBitmap(LPCTSTR filename)
    {
        CPrintDialog printDlg(FALSE);
        // printDlg.GetDefaults();
    
        if (printDlg.DoModal() == IDCANCEL)
            return FALSE;
    
        CDC dc;
        if (!dc.Attach(printDlg.GetPrinterDC()))
        {
            AfxMessageBox(_T("未发现发打印设备"));
            return FALSE;
        }
    
        dc.m_bPrinting = TRUE;
        DOCINFO di;
        // 初始化打印信息
        ::ZeroMemory(&di, sizeof(DOCINFO));
        di.cbSize = sizeof(DOCINFO);
        di.lpszDocName = filename;
        BOOL bPrintingOK = dc.StartDoc(&di); // 开始打印
    
        CPrintInfo Info;
        Info.SetMaxPage(1); // 只打印一页
        int maxw = dc.GetDeviceCaps(HORZRES);
        int maxh = dc.GetDeviceCaps(VERTRES);
        Info.m_rectDraw.SetRect(0, 0, maxw, maxh);
        for (UINT page = Info.GetMinPage(); page <=Info.GetMaxPage() && bPrintingOK; page++)
        {
            dc.StartPage(); // 开始打印新的一页
            Info.m_nCurPage = page;
            CBitmap bitmap;
    
            // 加载位图
            if (!bitmap.Attach(::LoadImage(::GetModuleHandle(NULL), filename, IMAGE_BITMAP, 0, 0,LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE)))
            {
                AfxMessageBox(_T("位图加载失败!"));
                return FALSE;
            }
            BITMAP bm;
            bitmap.GetBitmap(&bm);
            int w = bm.bmWidth;
            int h = bm.bmHeight;
            // 创建内存设备上下文
            CDC memDC;
            memDC.CreateCompatibleDC(&dc);
            CBitmap *pBmp = memDC.SelectObject(&bitmap);
            memDC.SetMapMode(dc.GetMapMode());
            dc.SetStretchBltMode(HALFTONE);
            // 拉伸打印
            dc.StretchBlt(0, 0, maxw, maxh, &memDC, 0, 0, w, h, SRCCOPY);
            // clean up
            memDC.SelectObject(pBmp);
            // end page
            bPrintingOK = (dc.EndPage() > 0);
        }
        if (bPrintingOK)
            dc.EndDoc(); // 打印完成
        else
    
            dc.AbortDoc(); // 终止打印
    
        return TRUE;
    }
    
    void CPrintDemoDlg::OnBnClickedOk()
    {
        BOOL bRet = PrintBitmap(_T("1.bmp"));
    
        if (bRet)
            AfxMessageBox(_T("打印完成"));
    }
  • ANSI和UNICODE互转,微软提供,无BUG

    ANSI和UNICODE互转,微软提供,无BUG。

    来源:https://support.microsoft.com/en-us/kb/138813

    /*
    * AnsiToUnicode converts the ANSI string pszA to a Unicode string
    * and returns the Unicode string through ppszW. Space for the
    * the converted string is allocated by AnsiToUnicode.
    */
    
    HRESULT __fastcall AnsiToUnicode( LPCSTR pszA , LPOLESTR * ppszW)
    {
    
                     ULONG cCharacters;
                     DWORD dwError;
    
                     // If input is null then just return the same.
                     if (NULL == pszA)
                    {
                                    * ppszW = NULL ;
                                     return NOERROR ;
                    }
    
                     // Determine number of wide characters to be allocated for the
                     // Unicode string.
                    cCharacters = strlen( pszA ) + 1;
    
                     // Use of the OLE allocator is required if the resultant Unicode
                     // string will be passed to another COM component and if that
                     // component will free it. Otherwise you can use your own allocator.
                    * ppszW = (LPOLESTR )CoTaskMemAlloc(cCharacters * 2);
                     if (NULL == * ppszW)
                                     return E_OUTOFMEMORY ;
    
                     // Covert to Unicode.
                     if (0 == MultiByteToWideChar(CP_ACP , 0, pszA, cCharacters,
                                    * ppszW , cCharacters))
                    {
                                    dwError = GetLastError();
                                    CoTaskMemFree(* ppszW );
                                    * ppszW = NULL ;
                                     return HRESULT_FROM_WIN32(dwError);
                    }
    
                     return NOERROR ;
                     /*
                    * UnicodeToAnsi converts the Unicode string pszW to an ANSI string
                    * and returns the ANSI string through ppszA. Space for the
                    * the converted string is allocated by UnicodeToAnsi.
                    */
    }
    
    HRESULT __fastcall UnicodeToAnsi( LPCOLESTR pszW , LPSTR * ppszA)
    {
    
                     ULONG cbAnsi, cCharacters;
                     DWORD dwError;
    
                     // If input is null then just return the same.
                     if (pszW == NULL)
                    {
                                    * ppszA = NULL ;
                                     return NOERROR ;
                    }
    
                    cCharacters = wcslen( pszW ) + 1;
                     // Determine number of bytes to be allocated for ANSI string. An
                     // ANSI string can have at most 2 bytes per character (for Double
                     // Byte Character Strings.)
                    cbAnsi = cCharacters * 2;
    
                     // Use of the OLE allocator is not required because the resultant
                     // ANSI  string will never be passed to another COM component. You
                     // can use your own allocator.
                    * ppszA = (LPSTR )CoTaskMemAlloc(cbAnsi);
                     if (NULL == * ppszA)
                                     return E_OUTOFMEMORY ;
    
                     // Convert to ANSI.
                     if (0 == WideCharToMultiByte(CP_ACP , 0, pszW, cCharacters, * ppszA ,
                                    cbAnsi, NULL , NULL ))
                    {
                                    dwError = GetLastError();
                                    CoTaskMemFree(* ppszA );
                                    * ppszA = NULL ;
                                     return HRESULT_FROM_WIN32(dwError);
                    }
                     return NOERROR ;
    
    }
    

    用法

    LPOLESTR pszFileNameW;
    AnsiToUnicode(lpszName, &pszFileNameW);
    m_list.InsertItem(0, pszFileNameW);

    方法2:

    char * lpszName = "ABC";
    USES_CONVERSION ;
    TCHAR *p = A2W (lpszName);
    
    //同样,还有 W2A

    方法3

    #include <cstdlib>
    
    char * lpszName = "ABC";
    TCHAR wszName[32];
    mbstowcs(wszName, lpszName, 32);
    
    //UINCODE转ANSI
    wcstombs(lpszName, wszName, 32);

  • 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;
    }
  • MFC的AfxBeginThread函数

    AfxBeginThread是MFC封装的函数,返回的是CWinThread*,不能用于CloseHandleAfxBeginThread在线程执行完后会句柄资源自动释放。

    如果是::CreateThread创建的线程则要手工调用CloseHandle释放线程句柄。

  • CInternetSession 的头文件 

    CInternetSession 的头文件 :

    #include <afxinet.h>

  • VS2013添加自定义资源

    VS2013添加自定义资源,在资源视图上点击右键,添加资源。

    随便选一个,比如bitmap类型,并点击导入。

    在打开的选择文件窗口选择“所有文件类型”

    选择我们要导入的文件,并确定。

    这时会弹出一个圣诞框,要求输入自定义类型名。输入名称后,自定义文件便被导入进来。

  • MFC中ToString()、Convert.ToString()、(string)、as string 的区别

    通常 object 到 string 有四种方式(假设有object obj):obj.ToString()、Convert.ToString()、(string)obj、obj as string。他们都能将 object 对象转换成 string 对象。我就讲讲他们的异同以及在实际中应该使用哪个。

    前两个方法通常是由别的对象得到 string 对象,它们间的区别只表现在要转换的对象为 null 时,如果 obj 为 null,调用 obj.ToString 方法会导致 NullReferenceException 异常,调用 Convert.ToString 不会抛出异常而返回一个 null。

    用强制转换(string)obj 要求 obj 的运行时类型必须是 string。如果不是,就会抛出异常。

    用 as 方法则会相对平稳,当 obj 的运行时类型不是 string 时会返回 null 而不抛出异常。

    所以在通常在我们需要得到某个对象的 string 表达形式时,我们应该使用 ToString 和 Convert.ToString,这时候你就得根据情形选一个,假如你能保证你的对象不为 null,则两个差不多。如果有可能为null,你就应该用 Convert.ToString,如果你希望它为 null 的时候抛出异常,那么当然可以选择 ToString。

    编者注:

    这里是说 object 到 string,如果在其它类型上调用第一种 ToString(),得到的不一定是实际的内容,可能是对该类的描述,这取决于该类如何实现ToString() 方法

  • 关于SetCapture和GetCapture

    正常情况下,鼠标指针位于哪个窗口区域内,鼠标消息就自动发给哪个窗口。如果调用了SetCapture,之后无论鼠标的位置在哪,鼠标消息都发给指定的这个窗口,直到调用ReleaseCapture或者调用SetCapture设置另一个窗口为止。
    很多时候,窗口或控件在鼠标按下后,需要知道鼠标移动和放开的情况,例如按钮在鼠标按下后会变为“按下”状态,鼠标移出按钮区域时“弹起”,所以按钮控件需要在鼠标按下时SetCapture,鼠标放开后ReleaseCapture
    GetCapture只是检查一下当前是哪个窗口捕获了鼠标,通常不需要调用。

  • MFC中去掉窗口类型为Overlapped的标题栏

    MFC中去掉窗口类型为Overlapped的标题栏

    ModifyStyle(WS_CAPTION, NULL, SWP_DRAWFRAME);

  • CHtmlView, 页面载入快播播放器时, 窗口关闭后, 出现内存访问失败的问题

    CHtmlView, 页面载入快播播放器时, 窗口关闭后, 出现内存访问失败的问题。

    如果遇到关闭带网页的窗口后,崩溃的问题,可以

    1. 打开about:blank空白页
    2. ShowWindow(SW_HIDE);
    3. SetTimer设置定时器,在定时器里关掉窗口

    ———– 解决页面嵌入快播播放器里,崩溃的问题 2011年9月25日 17时48分03秒

    开发环境: VS2003