阿杰 发表于 2012-4-21 09:35:50

VC++编程技巧20法

1. 如何激活当前屏幕保护程序
// 激活当前屏幕保护程序, jingzhou xu
PostMessage(WM_SYSCOMMAND,SC_SCREENSAVE,0);
2. 如何禁止/启用屏幕保护及电源管理
static UINT dss_GetList[] = {SPI_GETLOWPOWERTIMEOUT, SPI_GETPOWEROFFTIMEOUT, SPI_GETSCREENSAVETIMEOUT};
static UINT dss_SetList[] = {SPI_SETLOWPOWERTIMEOUT, SPI_SETPOWEROFFTIMEOUT, SPI_SETSCREENSAVETIMEOUT};
static const int dss_ListCount = _countof(dss_GetList);
禁止屏幕保护及电源管理?
{
m_pValue = new int;
for (int x=0;x<dss_ListCount;x++)
{
// 禁止屏幕保护及电源管理
VERIFY(SystemParametersInfo (dss_SetList, 0, NULL, 0));
}
delete[] m_pValue;
}
启用屏幕保护及电源管理?
{
m_pValue = new int;
for (int x=0;x<dss_ListCount;x++)
{
//启用屏幕保护及电源管理
VERIFY(SystemParametersInfo (dss_SetList, m_pValue, NULL, 0));
}
delete[] m_pValue;
}
3. 如何激活和关闭IE浏览器
//激活并打开IE
void lounchIE()
{
HWND h=FindWindowEx(NULL,NULL,NULL,
                      "Microsoft Internet Explorer") ;
ShellExecute(h,"open","C:\\simple.html",
               NULL,NULL,SW_SHOWNORMAL);
}
//关闭IE及其它应用
void CloseIE()
{
int app=BSM_APPLICATIONS;
unsigned longbsm_app=(unsigned long )app;
BroadcastSystemMessage(BSF_POSTMESSAGE,&bsm_app,
                         WM_CLOSE,NULL,NULL);
}
4. 如何给树控件加入工具提示
首先给树控件加入TVS_INFOTIP属性风格,如下所示:
if (!m_ctrlTree.Create(WS_CHILD|WS_VISIBLE|
TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT|TVS_SHOWSELALWAYS|TVS_INFOTIP,
//加入提示TVS_INFOTIP,jingzhou xu(树控件ID:100)
CRect(0, 0, 0, 0), &m_wndTreeBar, 100))
{
TRACE0("Failed to create instant bar child\n");
return -1;
}
其次加入映射消息声明,如下所示:
afx_msg void OnGetInfoTip(NMHDR* pNMHDR,LRESULT* pResult);      
//树控件上加入提示消息,jingzhou xu   
ON_NOTIFY(TVN_GETINFOTIP, 100, OnGetInfoTip)
//树控件条目上加入提示,jingzhou xu
最后加入呼应涵数处理:
void CCreateTreeDlg::OnGetInfoTip(NMHDR* pNMHDR,
                                    LRESULT* pResult)
{
*pResult = 0;
NMTVGETINFOTIP* pTVTipInfo = (NMTVGETINFOTIP*)pNMHDR;
LPARAM itemData = (DWORD) pTVTipInfo->lParam;
//对应每个条目的数据
HTREEITEM hItem = pTVTipInfo->hItem;
CString tip;
HTREEITEM hRootItem = m_chassisTree.GetRootItem();
if (hRootItem != pTVTipInfo->hItem)
{
    tip = "树结点的提示";
}
else
{
    tip = "树根上的提示";
}
strcpy(pTVTipInfo->pszText, (LPCTSTR) tip);
}
5. 如何获取系统信息框的路径
#include <atlbase.h>
#define IDS_REG_KEY_MSINFO_PATH1 _T( "Software\\Microsoft\\Shared Tools\\MSInfo" )
#define IDS_REG_KEY_MSINFO_PATH2 _T( "Software\\Microsoft\\Shared Tools Location" )
#define IDS_REG_VAL_MSINFO_PATH1 _T( "Path" )
#define IDS_REG_VAL_MSINFO_PATH2 _T( "MSInfo" )
#define IDS_MSINFO_EXE_NAME      _T( "MSInfo32.exe" )
//...
BOOL GetSysInfoPath( CString& strPath )
{      
    strPath.Empty();
    LPTSTRpszPath = strPath.GetBuffer( MAX_PATH );
    CRegKey reg;
    DWORD   dwSize= MAX_PATH;
    LONG    nRet    = reg.Open( HKEY_LOCAL_MACHINE, IDS_REG_KEY_MSINFO_PATH1, KEY_READ );
    // 在注册表中寻找第一个"MSInfo32.exe" 位置
    if ( nRet == ERROR_SUCCESS )
    {
      #if ( _MFC_VER >= 0x0700 )
            nRet = reg.QueryStringValue( IDS_REG_VAL_MSINFO_PATH1, pszPath, &dwSize );
      #else
            nRet = reg.QueryValue( pszPath, IDS_REG_VAL_MSINFO_PATH1, &dwSize );
      #endif
      reg.Close();
    }
    // 如果第一次寻找失败,则进行第二次寻找
    if ( nRet != ERROR_SUCCESS )
    {
      nRet = reg.Open( HKEY_LOCAL_MACHINE, IDS_REG_KEY_MSINFO_PATH2, KEY_READ );
      if ( nRet == ERROR_SUCCESS )
      {
            #if ( _MFC_VER >= 0x0700 )
                reg.QueryStringValue( IDS_REG_VAL_MSINFO_PATH2, pszPath, &dwSize );
            #else
                reg.QueryValue( pszPath, IDS_REG_VAL_MSINFO_PATH2, &dwSize );
            #endif
            // 路径名不包括EXE文件名
            if ( nRet == ERROR_SUCCESS )
                VERIFY( ::PathAppend( pszPath, IDS_MSINFO_EXE_NAME ) );
            reg.Close();
      }
    }
    strPath.ReleaseBuffer();
    strPath.FreeExtra();
    // 检查文件是否有效.   
    return ::PathFileExists( strPath );
}
6. 如何直接运行一个资源中的程序
bool Run()
   {
CFile f;
char* pFileName = "Execution.exe";
if( !f.Open( pFileName, CFile::modeCreate | CFile::modeWrite, NULL ) )
{
AfxMessageBox("Can not create file!");
return 0;
}
      CString path = f.GetFilePath();
HGLOBAL hRes;
HRSRC hResInfo;
   //获取应用实例
HINSTANCE insApp = AfxGetInstanceHandle();
   //寻找EXE资源名
hResInfo = FindResource(insApp,(LPCSTR)IDR_EXE4,"EXE");
hRes = LoadResource(insApp,hResInfo );   // Load it
DWORD dFileLength = SizeofResource( insApp, hResInfo );//计算EXE文件大小
f.WriteHuge((LPSTR)hRes,dFileLength);//写入临时文件
f.Close();
HINSTANCE HINSsd = ShellExecute(NULL, "open",path, NULL, NULL, SW_SHOWNORMAL);> //运行它.
return 1;
}
7. 如何遍历整个目录
#include <windows.h>
#include <shlobj.h>
//浏览目录.
void BrowseFolder( void )
{
TCHAR path;
BROWSEINFO bi = { 0 };
bi.lpszTitle = ("递归调用所有目录");
LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );
if ( pidl != 0 )
{
// 获取目录路径
SHGetPathFromIDList ( pidl, path );
//设置为当前路径
SetCurrentDirectory ( path );
//搜索所有子目录
SearchFolder( path );
// 释放内存
IMalloc * imalloc = 0;
if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
{
imalloc->Free ( pidl );
imalloc->Release ( );
}
}
//搜索其下所有子目录及文件.
void SearchFolder( TCHAR * path )
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
TCHAR filename[ MAX_PATH + 256 ];
TCHAR pathbak[ MAX_PATH ];
//复制初始用户选择目录
strcpy( pathbak, path );
//寻找第一个文件
hFind = FindFirstFile ( "*.*", &FindFileData );
//搜索所有文件及子目录
do
{
if ( hFind != INVALID_HANDLE_VALUE )
{
//如果是当前目录或父目录,跳过
if ( ! ( strcmp( FindFileData.cFileName, "." ) ) || ! ( strcmp( FindFileData.cFileName, ".." ) ) )
{
continue;
}
//恢复初始用户选择目录
strcpy( path, pathbak );
//列出所有发现的文件
sprintf( path, "%s\\%s", path, FindFileData.cFileName );
//如果 SetCurrentDirectory 成功的话,则它是一个目录,递归调用继续搜索子目录
if ( ( SetCurrentDirectory( path ) ) )
{
SearchFolder( path );
}
         //插入文件及路径名到列表框m_listbox_hwnd中
            SendMessage( m_listbox_hwnd, LB_ADDSTRING, 0, path );
       //<--INSERT WHAT YOU WANT DONE HERE!
}
}
while ( FindNextFile ( hFind, &FindFileData ) && hFind != INVALID_HANDLE_VALUE );
FindClose ( hFind );
}
8. 如何禁止/启用系统热键
bool bOld;
禁止系统热键?
//屏蔽掉系统键
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,true,&bOld,SPIF_UPDATEINIFILE);
启用系统热键?
//恢复系统热键
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,false,&bOld,SPIF_UPDATEINIFILE);
9. 如何隐藏/显示WINDOWS系统任务栏
隐藏系统任务栏?
//隐藏WINDOWS系统任务栏
::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_HIDE);
显示系统任务栏?
//恢复WINDOWS系统任务栏正常显示
::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_SHOW);
10. 如何实现窗口到系统区图标11. 间的动画效果
//*********************************************************
//* 名称:FindTrayWnd
//* 作者:徐景周(jingzhou_xu@163.net)
//* 功能:在显示窗体动画效果前,先寻找系统区位置
//**********************************************************
BOOL CALLBACK FindTrayWnd(HWND hwnd, LPARAM lParam)
{
    TCHAR szClassName;
    GetClassName(hwnd, szClassName, 255);
    // 比较窗口类名
    if (_tcscmp(szClassName, _T("TrayNotifyWnd")) == 0)
    {
      CRect *pRect = (CRect*) lParam;
      ::GetWindowRect(hwnd, pRect);
      return TRUE;
    }
    // 当找到时钟窗口时表示可以结束了
    if (_tcscmp(szClassName, _T("TrayClockWClass")) == 0)
    {
      CRect *pRect = (CRect*) lParam;
      CRect rectClock;
      ::GetWindowRect(hwnd, rectClock);
      pRect->right = rectClock.left;
      return FALSE;
    }
    return TRUE;
}
//********************************************************
//* 名称:WinAnimation
//* 作者:徐景周(jingzhou_xu@163.net)
//* 功能:显示窗口动画效果的涵数
//*********************************************************
void CScreenSnapDlg::WinAnimation(BOOL ShowFlag)
{
    CRect rect(0,0,0,0);
    // 查找托盘窗口
    CWnd* pWnd = FindWindow("Shell_TrayWnd", NULL);
    if (pWnd)
    {
      pWnd->GetWindowRect(rect);
EnumChildWindows(pWnd->m_hWnd, FindTrayWnd, (LPARAM)&rect);
//rect 为托盘区矩形
CRect rcWnd;
GetWindowRect(rcWnd);
if(ShowFlag) //窗体滑向系统区
DrawAnimatedRects(GetSafeHwnd(),IDANI_CAPTION,rcWnd,rect);
else //窗体从系统区滑出
DrawAnimatedRects(GetSafeHwnd(),IDANI_CAPTION,rect,rcWnd);
    }
}
用法如下:
if(IsWindowVisible())//窗体是否已隐藏
{
ShowWindow(SW_HIDE);         //先隐藏窗体
WinAnimation(true);      //窗体动画滑入到系统区中
}
else
{
WinAnimation(false);//窗体动画从系统区滑出
ShowWindow(SW_SHOW);
}
12. 如何判断当前操作系统的版本
//--------------------------------------------------------
//判断操作系统涵数及变量,jingzhou xu
typedef enum tagWin32SysType{
Windows32s,
WindowsNT3,
Windows95,
Windows98,
WindowsME,
WindowsNT4,
Windows2000,
WindowsXP
}Win32SysType;
//判断操作系统涵数及变量,jingzhou xu
Win32SysType IsShellSysType()
{
Win32SysTypeShellType;
DWORD winVer;
OSVERSIONINFO *osvi;
winVer=GetVersion();
if(winVer<0x80000000){/*NT */
ShellType=WindowsNT3;
osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
if (osvi!=NULL){
memset(osvi,0,sizeof(OSVERSIONINFO));
osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(osvi);
if(osvi->dwMajorVersion==4L)ShellType=WindowsNT4;
else if(osvi->dwMajorVersion==5L&&osvi->dwMinorVersion==0L)ShellType=Windows2000;
else if(osvi->dwMajorVersion==5L&&osvi->dwMinorVersion==1L)ShellType=WindowsXP;
free(osvi);
}
}
else if(LOBYTE(LOWORD(winVer))<4)
ShellType=Windows32s;
else{
ShellType=Windows95;
osvi= (OSVERSIONINFO *)malloc(sizeof(OSVERSIONINFO));
if (osvi!=NULL){
memset(osvi,0,sizeof(OSVERSIONINFO));
osvi->dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(osvi);
if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==10L)ShellType=Windows98;
else if(osvi->dwMajorVersion==4L&&osvi->dwMinorVersion==90L)ShellType=WindowsME;
free(osvi);
}
}
return ShellType;
}
//---------------------------------------------------------------
13. 如何在指14. 定矩形框内水平/垂直显示多行文字
///////////////////////////////////////////////////////
//说明:
//在矩形框中水平或垂直显示多行文字,jingzhou xu.
//lMode: 排列方式,0:水平方式; 1:垂直对齐
//lHori: 水平对齐方式, 0:左对齐; 1:居中; 2:右对齐; 3:自定义
//lVert: 垂直对齐方式, 0:顶对齐; 1:居中; 2:底对齐; 3:自定义
///////////////////////////////////////////////////////
CRect DrawTitleInRect(CDC *pDC, CString szString,
LPRECT lpRect, long lMode, long lHori, long lVert)
{
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
int tmpWidth=tm.tmAveCharWidth, tmpHeight=tm.tmHeight;
CRect rcInner(lpRect);
if(lMode==0)
{
rcInner.left+=tmpWidth;
rcInner.right-=tmpWidth;
rcInner.top-=tmpWidth;
rcInner.bottom+=tmpWidth;
}
if(lMode==1)
{
rcInner.left+=tmpWidth;
rcInner.right=rcInner.left+tmpWidth;
rcInner.top-=tmpWidth;
rcInner.bottom+=tmpWidth;
}
pDC->DrawText(szString, rcInner,DT_CALCRECT);
switch(lHori)
{
case 0:
break;
case 1:
{
long xOutCent=(lpRect->right+lpRect->left)/2;
long xInnCent=(rcInner.right+rcInner.left)/2;
rcInner.left+=(xOutCent-xInnCent);
rcInner.right+=(xOutCent-xInnCent);
}
break;
case 2:
{
long lInWidth=rcInner.right-rcInner.left;
rcInner.right=lpRect->right-tmpWidth;
rcInner.left=rcInner.right-lInWidth;
}
break;
default:
break;
}
switch(lVert)
{
case 0:
break;
case 1:
{
long yOutCent=(lpRect->bottom+lpRect->top)/2;
long yInnCent=(rcInner.bottom+rcInner.top)/2;
rcInner.top-=(yInnCent-yOutCent);
rcInner.bottom-=(yInnCent-yOutCent);
}
break;
case 2:
{
long lInHeigh=rcInner.top-rcInner.bottom;
rcInner.bottom=lpRect->bottom+tmpWidth;
rcInner.top=rcInner.bottom+lInHeigh;
}
break;
default:
break;
}
//--------------------------------------------------------------
//功能:根据新、老矩形,重新计算行数,使文字多行显示,jingzhou xu
//--------------------------------------------------------------
//一行中最大字符数
int nMaxLineChar = abs(lpRect->right - lpRect->left) / tmpWidth ;
//记录当前行的宽度
short theLineLength=0;
//记录当前行中汉字字节数,以防止将一半汉字分为两行
unsigned short halfChinese=0;
for(int i=0; i<=szString.GetLength()-1; i++)
{
if(((unsigned char)szString.GetAt(i) == 0x0d) &&
((unsigned char)szString.GetAt(i+1) == 0x0a))
theLineLength=0;
//大于0xa1的字节为汉字字节
if((unsigned char)szString.GetAt(i) >= 0xA1)
halfChinese++;
theLineLength++;
//如果行宽大于每行最大宽度,进行特殊处理
if(theLineLength > nMaxLineChar)
{
//防止将一个汉字分为两行,回溯
if(halfChinese%2)
{
szString.Insert(i,(unsigned char)0x0a);
szString.Insert(i,(unsigned char)0x0d);
}
else
{
szString.Insert(i-1,(unsigned char)0x0a);
szString.Insert(i-1,(unsigned char)0x0d);
}
theLineLength = 0;
}
}
//重新计算矩形边界范围
// int tmpLine = int(abs(szString.GetLength()*tmpWidth /
// abs(lpRect->right - lpRect->left)-0.5));
// tmpLine += (szString.GetLength()*tmpWidth %
// abs(lpRect->right - lpRect->left))? 1 : 0;
// if(tmpLine == 0)
// tmpLine = 1;
if(rcInner.bottom > lpRect->bottom)
rcInner.bottom = lpRect->bottom;
if(rcInner.top < lpRect->top)
rcInner.top = lpRect->top;
//--------------------------------------------------------------
if(lHori==0)
pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_LEFT);
else if(lHori==1)
pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_CENTER);
else if(lHori==2)
pDC->DrawText(szString, rcInner, DT_WORDBREAK|DT_RIGHT);
return rcInner;
}
15. 如何在指16. 定矩形中旋转显示文字
///////////////////////////////////////////////////////
//说明:
//在矩形框中旋转方式显示文字,jingzhou xu
//参数:
//pDC: DC指针
//str: 显示文字
//rect: 显示范围
//angle: 旋转角度
// nOptions: ExtTextOut()中相应设置<ETO_CLIPPED 和 ETO_OPAQUE>
///////////////////////////////////////////////////////
void DrawRotatedText(CDC* pDC, const CString str, CRect rect,
                     double angle, UINT nOptions)
{
   //按比例转换角度值
   double pi = 3.141592654;
   double radian = pi * 2 / 360 * angle;
   //获取显示文字中心点
   CSize TextSize = pDC->GetTextExtent(str);
   CPoint center;
   center.x = TextSize.cx / 2;
   center.y = TextSize.cy / 2;
   //计算显示文字新的中心点
   CPoint rcenter;
   rcenter.x = long(cos(radian) * center.x - sin(radian) * center.y);
   rcenter.y = long(sin(radian) * center.x + cos(radian) * center.y);
   //绘制文字
   pDC->SetTextAlign(TA_BASELINE);
   pDC->SetBkMode(TRANSPARENT);
   pDC->ExtTextOut(rect.left + rect.Width() / 2 - rcenter.x,
                   rect.top + rect.Height() / 2 + rcenter.y,
                   nOptions, rect, str, NULL);
}
17. 如何将32 x 32像素图标18. 转换为16 x 16像素值的图标19.
HICON Convert32x32IconTo16x16(HICON h32x32Icon)
{
HDC hMainDC, hMemDC1, hMemDC2;
HICON h16x16Icon;
BITMAP bmp;
HBITMAP hOldBmp1, hOldBmp2;
ICONINFO IconInfo32x32, IconInfo16x16;
GetIconInfo(h32x32Icon, &IconInfo32x32);
hMainDC = ::GetDC(m_hWnd);
hMemDC1 = CreateCompatibleDC(hMainDC);
hMemDC2 = CreateCompatibleDC(hMainDC);
GetObject(IconInfo32x32.hbmColor, sizeof(BITMAP), &bmp);
IconInfo16x16.hbmColor = CreateBitmap( 16, 16,
                                       bmp.bmPlanes,
                                       bmp.bmBitsPixel,
                                       NULL);
hOldBmp1 = (HBITMAP) SelectObject( hMemDC1,
                                     IconInfo32x32.hbmColor);
hOldBmp2 = (HBITMAP) SelectObject( hMemDC2,
                                     IconInfo16x16.hbmColor);
StretchBlt(hMemDC2,
       0, 0,
       16, 16,
       hMemDC1,
       0, 0,
       32, 32,
       SRCCOPY
       );
GetObject(IconInfo32x32.hbmMask, sizeof(BITMAP), &bmp);
IconInfo16x16.hbmMask = CreateBitmap( 16, 16,
                                        bmp.bmPlanes,
                                        bmp.bmBitsPixel,
                                        NULL);
SelectObject(hMemDC1, IconInfo32x32.hbmMask);
SelectObject(hMemDC2, IconInfo16x16.hbmMask);
StretchBlt(hMemDC2,
             0, 0,
             16, 16,
             hMemDC1,
             0, 0,
             32, 32,
             SRCCOPY
       );
SelectObject(hMemDC1, hOldBmp1);
SelectObject(hMemDC2, hOldBmp2);
IconInfo16x16.fIcon = TRUE;
h16x16Icon = CreateIconIndirect(&IconInfo16x16);
DeleteObject(IconInfo32x32.hbmColor);
DeleteObject(IconInfo16x16.hbmColor);
DeleteObject(IconInfo32x32.hbmMask);
DeleteObject(IconInfo16x16.hbmMask);
DeleteDC(hMemDC1);
DeleteDC(hMemDC2);
::ReleaseDC(m_hWnd, hMainDC);
return h16x16Icon;
}
20. 如何建立一个灰度级图标21.
HICON CreateGrayscaleIcon(HICON hIcon)
{
HICON       hGrayIcon = NULL;
HDC         hMainDC = NULL,
            hMemDC1 = NULL,
            hMemDC2 = NULL;
BITMAP      bmp;
HBITMAP   hOldBmp1 = NULL,
            hOldBmp2 = NULL;
ICONINFO    csII, csGrayII;
BOOL      bRetValue = FALSE;
bRetValue = ::GetIconInfo(hIcon, &csII);
if (bRetValue == FALSE) return NULL;
hMainDC = ::GetDC(m_hWnd);
hMemDC1 = ::CreateCompatibleDC(hMainDC);
hMemDC2 = ::CreateCompatibleDC(hMainDC);
if (hMainDC == NULL ||
    hMemDC1 == NULL ||
    hMemDC2 == NULL)
      return NULL;
if (::GetObject(csII.hbmColor,
                sizeof(BITMAP), &
                amp;bmp))
{
    csGrayII.hbmColor =
         ::CreateBitmap(csII.xHotspot*2,
                        csII.yHotspot*2,
                        bmp.bmPlanes,
                        bmp.bmBitsPixel,
                        NULL);
    if (csGrayII.hbmColor)
    {
      hOldBmp1 =
         (HBITMAP)::SelectObject(hMemDC1,
                                 csII.hbmColor);
      hOldBmp2 =
         (HBITMAP)::SelectObject(hMemDC2,
                                 csGrayII.hbmColor);
      ::BitBlt(hMemDC2, 0, 0, csII.xHotspot*2,
               csII.yHotspot*2, hMemDC1, 0, 0,
               SRCCOPY);
      DWORD    dwLoopY = 0, dwLoopX = 0;
      COLORREF crPixel = 0;
      BYTE   byNewPixel = 0;
      for (dwLoopY = 0; dwLoopY < csII.yHotspot*2; dwLoopY++)
      {
      for (dwLoopX = 0; dwLoopX < csII.xHotspot*2; dwLoopX++)
      {
          crPixel = ::GetPixel(hMemDC2, dwLoopX, dwLoopY);
          byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) +
               (GetGValue(crPixel) * 0.587) +
               (GetBValue(crPixel) * 0.114));
          if (crPixel) ::SetPixel(hMemDC2,
                                  dwLoopX,
                                  dwLoopY,
                                  RGB(byNewPixel,
                                  byNewPixel,
                                  byNewPixel));
      } // for
      } // for
      ::SelectObject(hMemDC1, hOldBmp1);
      ::SelectObject(hMemDC2, hOldBmp2);
      csGrayII.hbmMask = csII.hbmMask;
      csGrayII.fIcon = TRUE;
      hGrayIcon = ::CreateIconIndirect(&csGrayII);
    } // if
    ::DeleteObject(csGrayII.hbmColor);
    //::DeleteObject(csGrayII.hbmMask);
} // if
::DeleteObject(csII.hbmColor);
::DeleteObject(csII.hbmMask);
::DeleteDC(hMemDC1);
::DeleteDC(hMemDC2);
::ReleaseDC(m_hWnd, hMainDC);
return hGrayIcon;
}
22. 如何按指23. 定角度旋转显示内存位图(用法和BitBlt类似)
void RotBlt(HDC destDC, int srcx1, int srcy1, int srcx2, int srcy2,
HDC srcDC , int destx1, int desty1 ,int thetaInDegrees ,DWORD mode)
{
double theta = thetaInDegrees * (3.14159/180);
//原图像原始大小
int width = srcx2 - srcx1;
int height = srcy2 - srcy1;
//原图像中心点
int centreX = int(float(srcx2 + srcx1)/2);
int centreY = int(float(srcy2 + srcy1)/2);
//判断出图像可以沿任意方向旋转的矩形框
if(width>height)height = width;
else
    width = height;
HDC memDC = CreateCompatibleDC(destDC);
HBITMAP memBmp = CreateCompatibleBitmap(destDC, width, height);
HBITMAP obmp = (HBITMAP) SelectObject(memDC, memBmp);
//内存DC新在中心点
int newCentre = int(float(width)/2);
//开始旋转
for(int x = srcx1; x<=srcx2; x++)
    for(int y = srcy1; y<=srcy2; y++)
    {
      COLORREF col = GetPixel(srcDC,x,y);
      int newX = int((x-centreX)*sin(theta)+(y-centreY)*cos(theta));
      int newY = int((x-centreX)*cos(theta)-(y-centreY)*sin(theta));
      SetPixel(memDC , newX + newCentre, newY + newCentre, col);
    }
//复制到目标DC上
BitBlt(destDC, destx1, desty1, width, height, memDC, 0,0,mode);
//释放内存
SelectObject(memDC, obmp);
DeleteDC(memDC);
DeleteObject(memBmp);
}
用法:
RotBlt(dc, 0,0,150,150,memDC,200,0, 45, SRCCOPY);
24. 如何将指25. 定的窗体,26. 以位图形式复27. 制到系统剪切28. 板上
void CScreenSnapDlg::toClipboard_Bio(CWnd * wnd, BOOL FullWnd)
{
   CDC *dc;
   if(FullWnd)
      { /* 抓取整个窗口 */
dc = new CWindowDC(wnd);
      } /* 抓取整个窗口 */
   else
      { /* 仅抓取客户区时 */
dc = new CClientDC(wnd);
      } /* 仅抓取客户区时 */
   CDC memDC;
   memDC.CreateCompatibleDC(dc);
   CBitmap bm;
   CRect r;
   if(FullWnd)
      wnd->GetWindowRect(&r);
   else
         wnd->GetClientRect(&r);
   CString s;
   wnd->GetWindowText(s);
   CSize sz(r.Width(), r.Height());
   bm.CreateCompatibleBitmap(dc, sz.cx, sz.cy);
   CBitmap * oldbm = memDC.SelectObject(&bm);
   memDC.BitBlt(0, 0, sz.cx, sz.cy, dc, 0, 0, SRCCOPY);
   //直接调用OpenClipboard(),而不用wnd->GetParent()->OpenClipboard();
wnd->OpenClipboard();
   ::EmptyClipboard();
   ::SetClipboardData(CF_BITMAP, bm.m_hObject);
   CloseClipboard();
//恢复原始环境
   memDC.SelectObject(oldbm);
   bm.Detach();
delete dc;
}
29. 如何替换HBITMAP中的颜色值
#define COLORREF2RGB(Color) (Color & 0xff00) |
      ((Color >> 16) & 0xff)| ((Color << 16) & 0xff0000)
HBITMAP ReplaceColor (HBITMAP hBmp,COLORREF cOldColor,COLORREF cNewColor)
{
    HBITMAP RetBmp=NULL;
    if (hBmp)
    {   
      HDC BufferDC=CreateCompatibleDC(NULL);   // 源位图DC
      if (BufferDC)
      {
            SelectObject(BufferDC,hBmp);   // 选入DC中
            HDC DirectDC=CreateCompatibleDC(NULL);      // 目标DC
            if (DirectDC)
            {
                // 获取源位图大小
                BITMAP bm;
                GetObject(hBmp, sizeof(bm), &bm);
                // 初始化BITMAPINFO信息,以便使用CreateDIBSection
                BITMAPINFO RGB32BitsBITMAPINFO;
                ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));
                RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
                RGB32BitsBITMAPINFO.bmiHeader.biWidth=bm.bmWidth;
                RGB32BitsBITMAPINFO.bmiHeader.biHeight=bm.bmHeight;
                RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1;
                RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32;
                UINT * ptPixels;   
                HBITMAP DirectBitmap= CreateDIBSection(DirectDC,
                                              (BITMAPINFO *)&RGB32BitsBITMAPINFO,
                                              DIB_RGB_COLORS,(void **)&ptPixels, NULL, 0);
                if (DirectBitmap)
                {
                  HGDIOBJ PreviousObject=SelectObject(DirectDC, DirectBitmap);
                  BitBlt(DirectDC,0,0,bm.bmWidth,bm.bmHeight,BufferDC,0,0,SRCCOPY);
                  // 转换 COLORREF 为 RGB
                  cOldColor=COLORREF2RGB(cOldColor);
                  cNewColor=COLORREF2RGB(cNewColor);
                  // 替换颜色
                  for (int i=((bm.bmWidth*bm.bmHeight)-1);i>=0;i--)
                  {
                        if (ptPixels==cOldColor) ptPixels=cNewColor;
                  }
                  // 修改位图 DirectBitmap
                  SelectObject(DirectDC,PreviousObject);
                  // 完成
                  RetBmp=DirectBitmap;
                }
                // 释放DC
                DeleteDC(DirectDC);
            }
            // 释放DC
            DeleteDC(BufferDC);
      }
    }
    return RetBmp;
}
用法:
HBITMAP hBmp2 = LoadBitmap(g_hinstance,MAKEINTRESOURCE(IDB_SAMPLEBITMAP));
HBITMAP hBmp = ReplaceColor(hBmp2,0xff0000,0x00ff00); // 替换蓝色为绿色
......
DeleteObject(hBmp2);
DeleteObject(hBmp);
30. 如何转换并保存位图
//*************************************************
//* 名称:DDBToDIB
//* 作者:徐景周(jingzhou_xu@163.net)
//* 功能:设备相关转换为设备无关位图
//**************************************************
HANDLE CScreenSnapDlg::DDBToDIB( CBitmap& bitmap,
DWORD dwCompression /* = BI_RGB */)
{
    BITMAP bm;
    BITMAPINFOHEADER    bi;
    LPBITMAPINFOHEADERlpbi;
    DWORD dwLen;
    HANDLE hDIB;
    HANDLE handle;
    HDC hDC;
    HPALETTE hPal;
    CWindowDC dc( this );
    CPalette pal;
    //如果支持调色板的话,则建立它
    if( dc.GetDeviceCaps( RASTERCAPS ) & RC_PALETTE )
    {
      UINT      nSize   = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
      LOGPALETTE* pLP   = (LOGPALETTE*)new BYTE;
      pLP->palVersion   = 0x300;
      pLP->palNumEntries = (unsigned short)GetSystemPaletteEntries( dc, 0, 255,
      pLP->palPalEntry );
      pal.CreatePalette( pLP );
      //释放
      delete[] pLP;
    }
    ASSERT( bitmap.GetSafeHandle() );
    //不支持BI_BITFIELDS类型
    if( dwCompression == BI_BITFIELDS )
      return NULL;
    //如果调色板为空,则用默认调色板
    hPal = (HPALETTE) pal.GetSafeHandle();
    if (hPal==NULL)
      hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
    //获取位图信息
    bitmap.GetObject(sizeof(bm),(LPSTR)&bm);
    //初始化位图信息头
    bi.biSize      = sizeof(BITMAPINFOHEADER);
    bi.biWidth      = bm.bmWidth;
    bi.biHeight         = bm.bmHeight;
    bi.biPlanes         = 1;
    bi.biBitCount      = (unsigned short)(bm.bmPlanes * bm.bmBitsPixel) ;
    bi.biCompression    = dwCompression;
    bi.biSizeImage      = 0;
    bi.biXPelsPerMeter    = 0;
    bi.biYPelsPerMeter    = 0;
    bi.biClrUsed      = 0;
    bi.biClrImportant    = 0;
    //计算信息头及颜色表大小
    int nColors = 0;
    if(bi.biBitCount <= 8)
      {
      nColors = (1 << bi.biBitCount);
      }
    dwLen= bi.biSize + nColors * sizeof(RGBQUAD);
    hDC = ::GetDC(NULL);
    hPal = SelectPalette(hDC,hPal,FALSE);
    RealizePalette(hDC);
    //为信息头及颜色表分配内存
    hDIB = GlobalAlloc(GMEM_FIXED,dwLen);
    if (!hDIB){
      SelectPalette(hDC,hPal,FALSE);
      ::ReleaseDC(NULL,hDC);
      return NULL;
    }
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
    *lpbi = bi;
    //调用 GetDIBits 计算图像大小
    GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
            (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);
    bi = *lpbi;
    //图像的每一行都对齐(32bit)边界
    if (bi.biSizeImage == 0){
      bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)
                        * bi.biHeight;
      if (dwCompression != BI_RGB)
            bi.biSizeImage = (bi.biSizeImage * 3) / 2;
    }
    //重新分配内存大小,以便放下所有数据
    dwLen += bi.biSizeImage;
    handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE) ;
    if (handle != NULL)
      hDIB = handle;
    else
      {
      GlobalFree(hDIB);
      //重选原始调色板
      SelectPalette(hDC,hPal,FALSE);
      ::ReleaseDC(NULL,hDC);
      return NULL;
      }
    //获取位图数据
    lpbi = (LPBITMAPINFOHEADER)hDIB;
    //最终获得的DIB
    BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),
                0L,                      //扫描行起始处
                (DWORD)bi.biHeight,      //扫描行数
                (LPBYTE)lpbi             //位图数据地址
                + (bi.biSize + nColors * sizeof(RGBQUAD)),
                (LPBITMAPINFO)lpbi,      //位图信息地址
                (DWORD)DIB_RGB_COLORS);//颜色板使用RGB
    if( !bGotBits )
    {
      GlobalFree(hDIB);
      SelectPalette(hDC,hPal,FALSE);
      ::ReleaseDC(NULL,hDC);
      return NULL;
    }
    SelectPalette(hDC,hPal,FALSE);
    ::ReleaseDC(NULL,hDC);
    return hDIB;
}
//*********************************************************
//* 名称:SaveBitmapToFile
//* 修改:徐景周(jingzhou_xu@163.net)
//* 功能:保存为位图文件
//**********************************************************
BOOL CScreenSnapDlg::SaveBitmapToFile(HBITMAP hBitmap , CString lpFileName)
{      
HDC hDC; //设备描述表
    int iBits; //当前显示分辨率下每个像素所占字节数
WORD            wBitCount; //位图中每个像素所占字节数
DWORD         dwPaletteSize=0,
//定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
dwBmBitsSize,
dwDIBSize, dwWritten;
BITMAP          Bitmap;      
BITMAPFILEHEADER   bmfHdr; //位图属性结构   
    BITMAPINFOHEADER   bi; //位图文件头结构      
LPBITMAPINFOHEADER lpbi; //位图信息头结构   
    HANDLE          fh, hDib, hPal,hOldPal=NULL;
//指向位图信息头结构,定义文件,分配内存句柄,调色板句柄
   //计算位图文件每个像素所占字节数
   hDC = CreateDC("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 if (iBits <= 24)
      wBitCount = 24;
   //计算调色板大小
   if (wBitCount <= 8)
      dwPaletteSize = (1 << wBitCount) *sizeof(RGBQUAD);
   //设置位图信息头结构
   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.biClrUsed         = 0;
   bi.biClrImportant      = 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);
   hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
       RealizePalette(hDC);
   }
   // 获取该调色板下新的像素值
   GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
(LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
   //恢复调色板   
   if (hOldPal)
   {
      SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
      RealizePalette(hDC);
      ::ReleaseDC(NULL, hDC);
   }
   //创建位图文件   
fh = CreateFile(lpFileName, 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;
}
31. 如何获取局域网上计算机名32. 及它们的IP地址
连接ws2_32.lib和 mpr.lib库
#include winsock2.h
CString strTemp;
struct hostent *host;
struct in_addr *ptr; // 检索IP地址
DWORD dwScope = RESOURCE_CONTEXT;
NETRESOURCE *NetResource = NULL;
HANDLE hEnum;
WNetOpenEnum( dwScope, NULL, NULL,
             NULL, &hEnum );
WSADATA wsaData;
WSAStartup(MAKEWORD(1,1),&wsaData);
if ( hEnum )
{
    DWORD Count = 0xFFFFFFFF;
    DWORD BufferSize = 2048;
    LPVOID Buffer = new char;
    WNetEnumResource( hEnum, &Count,
      Buffer, &BufferSize );
    NetResource = (NETRESOURCE*)Buffer;
    char szHostName;
    unsigned int i;
    for ( i = 0;
      i < BufferSize/sizeof(NETRESOURCE);
      i++, NetResource++ )
    {
      if ( NetResource->dwUsage ==
            RESOURCEUSAGE_CONTAINER &&
            NetResource->dwType ==
            RESOURCETYPE_ANY )
      {
            if ( NetResource->lpRemoteName )
            {
                CString strFullName =
                  NetResource->lpRemoteName;
                if ( 0 ==
                  strFullName.Left(2).Compare("\\\\") )   
                  strFullName =
                        strFullName.Right(
                            strFullName.GetLength()-2);
                gethostname( szHostName,
                  strlen( szHostName ) );
                host = gethostbyname(strFullName);
                if(host == NULL) continue;
                ptr = (struct in_addr *)
                  host->h_addr_list;                  
                // =. 分隔开IP:211.40.35.76.            
                int a = ptr->S_un.S_un_b.s_b1;// 211         
                int b = ptr->S_un.S_un_b.s_b2;// 40
                int c = ptr->S_un.S_un_b.s_b3;// 35
                int d = ptr->S_un.S_un_b.s_b4;// 76
                strTemp.Format("%s -->%d.%d.%d.%d",
                  strFullName,a,b,c,d);
                AfxMessageBox(strTemp);
            }
      }
    }
    delete Buffer;
    WNetCloseEnum( hEnum );
}
WSACleanup();

upring 发表于 2015-5-12 08:27:57

谢谢 很好 支持您了
页: [1]
查看完整版本: VC++编程技巧20法