返回列表 发帖

VC编程中20种各种编程技巧和方法

[这个贴子最后由bigblock在 2003/11/12 07:32pm 第 1 次编辑] 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); l 禁止屏幕保护及电源管理 { m_pValue = new int[dss_ListCount]; for (int x=0;xlParam; //对应每个条目的数据 HTREEITEM hItem = pTVTipInfo->hItem; CString tip; HTREEITEM hRootItem = m_chassisTree.GetRootItem(); if (hRootItem != pTVTipInfo->hItem) { tip = "树结点的提?quot;; } else { tip = "树根上的提示"; } strcpy(pTVTipInfo->pszText, (LPCTSTR) tip); } 5. 如何获取系统信息框的路径 #include #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(); LPTSTR pszPath = 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 #include //浏览目录. void BrowseFolder( void ) { TCHAR path[MAX_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; l 禁止系统热键 //屏蔽掉系统键 SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,true,&bOld,SPIF_UPDATEINIFILE); l 启用系统热键 //恢复系统热键 SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,false,&bOld,SPIF_UPDATEINIFILE); 9. 如何隐藏/显示WINDOWS系统任务栏 l 隐藏系统任务栏 //隐藏WINDOWS系统任务栏 ::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_HIDE); l 显示系统任务栏 //恢复WINDOWS系统任务栏正常显示 ::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_SHOW); 10. 如何实现窗口到系统区图标间的动画效果 //******************************************************************************** //* 名称:FindTrayWnd //* 作者:bigblock(bigblock@hackersky.net) //* 功能:在显示窗体动画效果前,先寻找系统区位置 //******************************************************************************** BOOL CALLBACK FindTrayWnd(HWND hwnd, LPARAM lParam) { TCHAR szClassName[256]; 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 //* 作者:bigblcok(bigblock@hackersky.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); } 11. 如何判断当前操作系统的版本 //------------------------------------------------------------------------------------------------ //判断操作系统涵数及变量,jingzhou xu typedef enum tagWin32SysType{ Windows32s, WindowsNT3, Windows95, Windows98, WindowsME, WindowsNT4, Windows2000, WindowsXP }Win32SysType; //判断操作系统涵数及变量,jingzhou xu Win32SysType IsShellSysType() { Win32SysType ShellType; 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; } //------------------------------------------------------------------------------------------------ 12. 如何在指定矩形框内水平/垂直显示多行文字 /////////////////////////////////////////////////////// //说明: // 在矩形框中水平或垂直显示多行文字,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; } 13. 如何在指定矩形中旋转显示文字 /////////////////////////////////////////////////////// //说明: // 在矩形框中旋转方式显示文字,jingzhou xu //参数: // pDC: DC指针 // str: 显示文字 // rect: 显示范围 // angle: 旋转角度 // nOptions: ExtTextOut()中相应设置 /////////////////////////////////////////////////////// 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); } 14. 如何将32 x 32像素图标转换为16 x 16像素值的图标 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; } 15. 如何建立一个灰度级图标 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; } 16. 如何按指定角度旋转显示内存位图(用法和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); 17. 如何将指定的窗体,以位图形式复制到系统剪切板上 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; } 18. 如何替换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); 19. 如何转换并保存位图 //******************************************************************************** //* 名称:DDBToDIB //* 作者:bigblock(bigblock@hackersky.net) //* 功能:设备相关转换为设备无关位图 //******************************************************************************** HANDLE CScreenSnapDlg::DDBToDIB( CBitmap& bitmap, DWORD dwCompression /* = BI_RGB */) { BITMAP bm; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; 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[nSize]; 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 //* 修改:bigblock(bigblock@hackersky.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; } 20. 如何获取局域网上计算机名及它们的IP地址 l 连接ws2_32.lib和 mpr.lib库 l #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[2048]; WNetEnumResource( hEnum, &Count, Buffer, &BufferSize ); NetResource = (NETRESOURCE*)Buffer; char szHostName[200]; 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[0]; // =. 分隔开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();

VC编程中20种各种编程技巧和方法

哎呀,好好看啊。
不要有歧义哦,我是说要好好地“看”

TOP

VC编程中20种各种编程技巧和方法

深奥,比起我的VFP要深奥多了!

TOP

VC编程中20种各种编程技巧和方法

晕死~~语言都不一样的.没几个能混在一起的啊.

TOP

返回列表 回复 发帖