《MFC编程小技巧.doc》由会员分享,可在线阅读,更多相关《MFC编程小技巧.doc(49页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、一、窗口类41、如何获取应用程序的实例句柄?42、如何通过代码获得应用程序主窗口的指针?43、如何在程序中获得其他程序的 图标?44、如何改变窗口的图标?55、如何改变窗口的缺省风格?56、如何将窗口居中显示?67、如何让窗口和 MDI窗口一启动就最大化和最小化?68、如何限制窗口的大小?69、如何使窗口不可见?610、如何使窗口始终在最前方?611、如何创建一个字回绕的CEditView712、通用控件的显示窗口713、移动窗口714、重置窗口的大小815、如何单击除了窗口标题栏以外的区域使窗口移动816、如何改变视窗的背景颜色1017、如何改变窗口标题1118、如何防止主框窗口在其说明中显
2、示活动的文档名1219、如何获取有关窗口正在处理的当前消息的信息1320、如何创建一个不规则形状的窗口1321、如何访问桌面窗口15二 应用程序161、如何编程结束应用程序?如何编程控制windows的重新引导?162、怎样加栽其他的应用程序?163、确定应用程序的路径174、获得各种目录信息175、如何自定义消息186、如何使程序保持极小状态?18三、工具条、状态栏、菜单191、如何在代码中获取工具条和状态条的指针192、如何使能和禁止工具条的工具提示193、如何设置工具条标题204、为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态205、如何给系统菜单添加一个菜单项
3、216、如何确定顶层菜单所占据的菜单行数21四、对话框221、如何创建和使用无模式对话框222、如何在对话框中显示一个位图243、如何改变对话或窗体视窗的背景颜色244、如何获取一个对话控件的指针265、对话框消息映射266、如何改变框对话或窗体视窗的背景颜色277、如何实现点一下对话框外面的区域,自动隐藏对话框?298、改变对话框背景颜色后,如何使控件的背景颜色和对话框背景颜色统一?32五、控件331、如何禁止和使能控件332、如何改变控件的字体343、如何在OLE控件中使用OLE_COLOR数据类型354、在不使用通用文件打开对话的情况下如何显示一个文件列表355、为什么旋转按钮控件看起来
4、倒转366为什么旋转按钮控件不能自动地更新它下面的编辑控件367、如何用位图显示下压按钮368、如何一个创建三态下压按钮379、如何动态创建控件3710、如何限制编辑框中的准许字符3811、如何改变控件的颜色3913、当向列表框中添加多个项时如何防止闪烁4114、如何向编辑控件中添加文本42六、GDI421、如何获取GDI对象的属性信息422、如何实现一个橡皮区矩形433、如何更新翻转背景颜色的文本464、如何创建一个具有特定点大小的字体475、如何计算一个串的大小476、如何显示旋转文本487、如何正确显示包含标签字符的串508、串太长时如何在其末尾显示一个省略号509、如何快速地格式化一个
5、CString对象5110、如何访问预定义的GDI对象5211、在用户环境中如何确定系统显示元素的颜色52七、视图类531、怎样改变视图的大小?532、如何改变一个CFormView的大小?533、如何改变一个视图的背景?534、如何使FormView中显示dialog时,不是凹的545、如何获得当前视图的指针?546、如何获得MDI程序的所有视图?5461、如何查询和设置系统参数5462、如何使用一个预定义的Windows光标5563、如何确定当前屏幕分辨率5664、如何检索原先的Task Manager应用程序使用的任务列表5665、如何确定Windows和Windows系统目录5766、
6、在哪儿创建临文件5868、用鼠标移动基于对话框的无标题栏程序的简单方法59一、窗口类1、如何获取应用程序的实例句柄?应用程序的 实例句柄保存在CWinAppIm_hInstance中,可以这么调用AfxGetInstancdHandle获得句柄.Example: HANDLE hInstance=AfxGetInstanceHandle();2、如何通过代码获得应用程序主窗口的指针?主窗口的 指针保存在CWinThread:m_pMainWnd中,调用 AfxGetMainWnd实现。AfxGetMainWnd() -ShowWindow(SW_SHOWMAXMIZED); /使程序最大化.3
7、、如何在程序中获得其他程序的 图标?两种方法:(1) SDK函数 SHGetFileInfo或使用 ExtractIcon获得图标资源的 handle,(2) SDK函数 SHGetFileInfo获得有关文件的 很多信息,如大小图标,属性,类型等.Example(1):在程序窗口左上角显示 NotePad图标.void CSampleView: OnDraw(CDC * pDC)if( : SHGetFileInfo(_T(c:pwin95notepad.exe),0,&stFileInfo,sizeof(stFileInfo),SHGFI_ICON)pDC -DrawIcon(10,10,
8、stFileInfo.hIcon);Example(2):同样功能,Use ExtractIcon Functionvoid CSampleView: OnDraw(CDC *pDC)HICON hIcon=: ExtractIcon(AfxGetInstanceHandle(),_T(NotePad.exe),0);if (hIcon &hIcon!=(HICON)-1)pDC-DrawIcon(10,10,hIcon);说明:获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到,如果是调用 win95下的画笔,应该用访问注册表的方法获得其路径,要作成一
9、个比较考究的程序,考虑应该全面点.4、如何改变窗口的图标?向窗口发送 WM_SECTION消息。Example:HICON hIcon=AfxGetApp() -LoadIcon(IDI_ICON);ASSERT(hIcon);AfxGetMainWnd() -SendMessage(WM_SECTION,TRUE,(LPARAM) hIcon);5、如何改变窗口的缺省风格?重栽 CWnd: PreCreateWindow并修改CREATESTRUCT结构来指定窗口风格和其他创建信息.Example: Delete Max Button and Set Original Windows Pos
10、ition and SizeBOOL CMainFrame: PreCreateWindow (CREATESTRUCT &cs)cs.style &=WS_MAXINIZEMOX;cs.x=cs.y=0;cs.cx=GetSystemMetrics(SM_CXSCREEN/2);cs.cy=GetSystemMetrics(SM_CYSCREEN/2);return CMDIFramewnd :PreCreateWindow(cs);6、如何将窗口居中显示?Easy, Call Function CWnd: Center WindowsExample(1): Center Window( )
11、; /Relative to its parent/ Relative to ScreenExample(2): Center Window(CWnd: GetDesktopWindow( );/Relative to Applications MainWindowAfxGetMainWnd( ) - Center Window( );7、如何让窗口和 MDI窗口一启动就最大化和最小化?先说窗口。在 InitStance函数中设定 m_nCmdShow的 取值.m_nCmdShow=SW_SHOWMAXMIZED ; /最大化m_nCmdShow=SW_SHOWMINMIZED ; /最小化m
12、_nCmdShow=SW_SHOWNORMAL ; /正常方式MDI窗口:如果是创建新的应用程序,可以用 MFC AppWizard的Advanced按钮并在MDI子窗口风格组中检测最大化或最小化;还可以重载 MDI Window的PreCreateWindow函数,设置WS_MAXMIZE or WS_MINMIZE;如果从 CMDIChildWnd派生,调用 OnInitialUpdate函数中的 CWnd:ShowWindow来指定 MDI Child Window的 风格。8、如何限制窗口的大小?也就是 FixedDialog形式。 Windows发送 WM_GETMAXMININFO
13、消息来跟踪,响应它,在 OnGetMAXMININFO中写代码:9、如何使窗口不可见?很简单,用SW_HIDE隐藏窗口,可以结合 FindWindow,ShowWindow控制.10、如何使窗口始终在最前方?两种途径.BringWindowToTop(Handle);SetWindowPos函数,指定窗口的 最顶风格,用WS_EX_TOPMOST扩展窗口的 风格Example:void ToggleTopMost( CWnd *pWnd)11、如何创建一个字回绕的CEditView 重载CWnd : : PreCreateWindow和修改CREATESTRUCT结构,关闭CEditView对
14、象的ES_AUTOHSCROLL和WS_HSCROLL风格位, 由于CEditView : : PreCreateWindow显示设置cs. style,调用基类函数后要修改cs . style。 BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&cs) /First call basse class function . BOOL bResutl =CEditView : : PreCreateWindow (cs) ; / Now specify the new window style . cs.style &= (ES_AUT
15、OHSCROLL WS_HSCROLL); return bResult ; 12、通用控件的显示窗口 MFC提供了几个CView派生的视窗类, 封装了通用控件的功能,但仍然使用工 作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表 控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。 13、移动窗口 调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口 有关(顶层窗口与屏幕有关)。调用CWnd : : MoveWindow时必须要指定窗口 的大小。 /Move win
16、dow to positoin 100 , 100 of its parent window . SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE SWP_NOAORDER); 14、重置窗口的大小 调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可调用 CWnd : : MoveWindow 但必须指定窗口的位置。 / Get the size of the window . Crect reWindow ; GetWindowRect (reWindow ); /Make the window twice
17、as wide and twice as tall . SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2, reWindow . Height () * 2, SWP_NOMOVE SWP_NOZORDER ); 15、如何单击除了窗口标题栏以外的区域使窗口移动 当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理 该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可 以使用ClassWizard处理该信息并调用基类函数, 如果函数返回HTCLIENT 则表明 鼠标在客房区域,返
18、回HTCAPTION表明鼠标在Windows的标题栏中。 UINT CSampleDialog : : OnNcHitTest (Cpoint point ) UINT nHitTest =Cdialog: : OnNcHitTest (point ); return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest ; 上述技术有两点不利之处, 其一是在窗口的客户区域双击时, 窗口将极大; 其二, 它不适合包含几个视窗的主框窗口。还有一种方法,当用户按下鼠标左键 使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTO
19、DOWN 信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。 void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point ) CView : : OnLButtonDow (nFlags , pont ); /Fool frame window into thinking somene clicked on its caption bar . GetParentFrame ( ) PostMessage ( WM_NCLBUTTONDOWN , HTCAPTION , MAKELPAR
20、AM (poitn .x , point .y) ); 该技术也适用于对话框和基于对的应用程序,只是不必调用CWnd : : GetParentFrame 。 void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point ) Cdialog : : OnLButtonDow (nFlags, goint ); /Fool dialog into thinking simeone clicked on its caption bar . PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAK
21、ELPARM (point.x , point. y ) ) 16、如何改变视窗的背景颜色 Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用 ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以 防止Windows擦除窗口。 /Paint area that needs to be erased. BOOL CSampleView : : OnEraseBkgnd (CDC* pDC) / Create a pruple brush. CBrush Brush (RGB (128 , 0 , 128) ); / Selec
22、t the brush into the device context . CBrush* pOldBrush = pDCSelcetObject (&brush); / Get the area that needs to be erased . CRect reClip ; pDCGetCilpBox (&rcClip); /Paint the area. pDC PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height ( ) , PATCOPY ); /Unselect brush out of device
23、 context . pDCSelectObject (pOldBrush ); / Return nonzero to half fruther processing . return TRUE; 17、如何改变窗口标题 调用CWnd : : SetWindowText可以改变任何窗口(包括控件)的标题。 /Set title for applications main frame window . AfxGetMainWnd ( ) SetWindowText (_T(Application title) ); /Set title for Views MDI child frame wi
24、ndow . GetParentFrame ( ) SetWindowText (_T (MDI Child Frame new title) ); /Set title for dialogs push button control. GetDigitem (IDC_BUTTON) SetWindowText (_T (Button new title ) ); 如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化 的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在 联机帮助中找不到它,它在AFXPRIV.H中半文档化
25、, 在以后发行的MFC中将文档化。 AfxSetWindowText的实现如下: voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew ) itn nNewLen= Istrlen (Ipaznew); TCHAR szOld 256; /fast check to see if text really changes (reduces flash in the controls ) if (nNewLen _contof (szOld) : : GetWindowText (hWndCrtl , szOld , _coun
26、tof (szOld) !=nNewLen Istrcmp (szOld , IpszNew )! = 0 /change it : : SetWindowText (hWndCtrl , IpszNew ); 18、如何防止主框窗口在其说明中显示活动的文档名 创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位, 如果不希望在 说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置 CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。 BOOL CMainFrame : : PreCreateWindow (CREA
27、TESTRUCT&cs) /Turn off FWS_ADDTOTITLE in main frame . cs.styel & = FWS_ADDTOTITLE ; return CMDIFrameWnd : : PreCreateWindow (cs ); 关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调 用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。 本文来自CSDN博客,转载请标明出处:ASSERT_VALID(pWnd);pWnd -SetWindowPos(pWnd- GetStyle( ) &W
28、S_EX_TOPMOST)?&wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE);19、如何获取有关窗口正在处理的当前消息的信息调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage来确定所选中的菜单项。viod CMainFrame : : OnCommmonMenuHandler ( )/Display selected menu item in debug window .TRACE (M
29、enu item %u was selected . n ,GetCruuentMessage ( ) wParam );20、如何创建一个不规则形状的窗口可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。Class CRoundDlg : public CDialogprivate :Crgn m_rgn : / window regi
30、on ;修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口:BOOL CRoundDlg : : OnInitDialog ( )CDialog : : OnInitDialog ( ) ;/Get size of dialog .CRect rcDialog ;GetClientRect (rcDialog );/ Create region and assign to window .m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width ( ) , rcDialog .Height ( ) );Se
31、tWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn , TRUE );return TRUE ;通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。voik CRoundDlg : : OnPaint ( )CPaintDC de (this) ; / device context for painting ./draw ellipse with out any borderdc. SelecStockObject (NULL_PEN);/get the RGB col
32、our components of the sphere colorCOLORREF color= RGB( 0 , 0 , 255);BYTE byRed =GetRValue (color);BYTE byGreen = GetGValue (color);BYTE byBlue = GetBValue (color);/ get the size of the view windowCrect rect ;GetClientRect (rect);/ get minimun number of unitsint nUnits =min (rect.right , rect.bottom
33、);/calculate he horiaontal and vertical step sizefloat fltStepHorz = (float) rect.right /nUnits ;float fltStepVert = (float) rect.bottom /nUnits ;int nEllipse = nUnits/3; / calculate how many to drawint nIndex ; / current ellipse that is being drawCBrush brush ; / bursh used for ellipse fill colorCB
34、rush *pBrushOld; / previous brush that was selected into dc/draw ellipse , gradually moving towards upper-right cornerfor (nIndex = 0 ; nIndes m_hWnd, hWnd) &: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)=0)+nCount;hWnd=: GetWindow (hWnd, GW_HWNDNEXT);二 应用程序1、如何编程结束应用程序?如何编程控制windows的重新引导?这是个很简单又是编程中经常
35、要遇到的问题.第一问,向窗口发送 WM_CLOSE消息,调用 CWnd:OnClose成员函数.允许对用户提示是否保存修改过的数据.Example: AfxGetMainWindow()-SendMessage(WM_CLOSE);还可以创建一个自定义的函数 Terminate Windowvoid Terminate Window(LPCSTR pCaption)CWnd *pWnd=Cwnd:FindWindow(NULL,pCaption);if (pWnd)pWnd -SendMessage(WM_CLOSE);说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改
36、变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时 FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。 在 机械出版社Windows 95 API开发人员指南一书有比较详细的介绍,这里就不再多说乐。第二问,Use ExitWindowsEx Function函数控制系统是重新引导,还是重启 windows.前面已经有人讲过乐,就不再提了。2、怎样加栽其他的应用程序?我记得这好象是出场频度很高的问题。三个SDK函数 winexec, shellexecute,createprocess可以使用。WinExec最简单,两个参数,
37、前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加栽一个无最大化按钮的 程序,呵呵就是Neterm,calc等等,就不会出现正常的 窗体,但是已经被加到任务列表里了。ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的 Example就是直接打开 c:temp1.txt,而不用加栽与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or Faq,偶猜就是这么作的啦.ShellExecute(NULL,NULL,_T(1.txt),NULL,_T(c:temp),SW_SHOWMAX
38、MIZED);CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的 Example:STARTUPINFO stinfo; /启动窗口的信息PROCESSINFO procinfo; /进程的信息CreateProcess(NULL,_T(notepad.exe),NULL,NULL.FALSE, NORMAL_PRIORITY_CLASS,NULL,NULL, &stinfo,&procinfo);3、确定应用程序的路径前些天好象有人问过这个问题.Use GetModuleFileName获得应用
39、程序的路径,然后去掉可执行文件名。Example:TCHAR exeFullPathMAX_PATH; / MAX_PATH在API中定义了吧,好象是128GetModuleFileName(NULL,exeFullPath,MAX_PATH)4、获得各种目录信息Windows目录: Use GetWindowsDirectory“Windows下的system目录: Use GetSystemDirectorytemp目录: Use GetTempPath 当前目录: Use GetCurrentDirectory请注意前两个函数的第一个参数为 目录变量名,后一个为缓冲区;后两个相反.5、如
40、何自定义消息也有人问过的,其实不难。(1)手工定义消息,可以这么写 #define WM_MY_MESSAGE(WM_USER+100),MS推荐的至少是 WM_USER+100;(2)写消息处理函数,用 WPARAM,LPARAM返回LRESULT.LRESULT CMainFrame:OnMyMessage(WPARAM wparam,LPARAM lParam)/加入你的处理函数(3)在类的 AFX_MSG处进行声明,也就是常说的宏映射6、如何使程序保持极小状态?很有意思的 问题这么办:在恢复程序窗体大小时, Windows会发送WM_QUERY-OPEN消息,用 ClassWizard
41、设置成员函数 OnQueryOpen() ,add following code:Bool CMainFrame: OnQueryOpen( )Return false;三、工具条、状态栏、菜单1、如何在代码中获取工具条和状态条的指针缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:/Get pointer to status bar .CStatusBar * pStatusBar =(CStatusBar *) AfxGetMainWnd ( ) GetDescendantWindow(AFX_IDW_STU