《VC编程一些技巧.docx》由会员分享,可在线阅读,更多相关《VC编程一些技巧.docx(12页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、VC编程一些技巧我将一幅图片作为对话框的背景,对话框的大小可以改变,并且可以最大化。这是在下面的代码中实现的:绘制背景图片BOOL CMyDlg:OnEraseBkgnd( CDC* pDC )CDialog:OnEraseBkgnd(pDC);CRect rcClient;GetClientRect(&rcClient);CBitmap mybitmap;mybitmap.LoadBitmap(IDB_BITMAP1);/我的图片BITMAP bmpInfo;mybitmap.GetBitmap(&bmpInfo);CDC dcMem;dcMem.CreateCompatibleDC(pDC
2、);CBitmap *pOldBitmap=dcMem.SelectObject(&mybitmap);pDC-StretchBlt(0, 0,rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, SRCAND );dcMem.SelectObject(pOldBitmap);dcMem.DeleteDC(); 我在对话框上加了两个EDIT BOX控件。我希望改变对话框大小时,控件的大小也改变所以我响应了ON_SIZE消息void CMyDlg:OnSize(UINT nTyp
3、e, int cx, int cy) CDialog:OnSize(nType, cx, cy); / TODO: Add your message handler code hereif(m_myedit1) CRect rc,rc1; RECT re; GetClientRect(&rc); re=rc; m_myedit2.GetRect(&rc1); m_myedit1.MoveWindow(re.left+10,re.top+10, rc.Width()-20,rc.Height()-15-50); m_myedit2.MoveWindow(re.left+10,rc.bottom-
4、40, rc.Width()-20,20); m_edit1=m_edit1+OnSize is executed; UpdateData(FALSE); VC让对话框显示就最大化Mfc 2008-07-17 14:10:04 阅读459 评论0 字号:大中小 订阅 .方法一:在OnInitDialog()函数中 ShowWindow(SW_SHOWMAXIMIZED); 初始化的时候方法二:当然,你可以获取屏幕大小,然后设置窗口位置/大小 /ShowWindow(SW_MAXIMIZE); / 获得屏幕分辨率 HDC hDesktopDC = CreateDC(_T(DISPLAY), NU
5、LL, NULL, NULL); int xScrn = GetDeviceCaps(hDesktopDC, HORZRES); int yScrn = GetDeviceCaps(hDesktopDC, VERTRES); MoveWindow(0, 0, xScrn, yScrn);写OnShowWindows消息响应,调showwindow(SW_SHOWMAXIMIZED)方法三:在DIALOG的OnInitDialog过程中加入 CDialog:OnInitDialog(); SetWindowPos(NULL,0,0,GetSystemMetrics(SM_CXSCREEN),Ge
6、tSystemMetrics(SM_CYSCREEN),0);禁止用鼠标移动窗口的方法(转载) 分类: VC编程技术 2008-04-14 16:25 在CMainFrame中添加消息相应void CMainFrame:OnNcLButtonDown(UINT nHitTest, CPoint point) / TODO: Add your message handler code here and/or call default if (nHitTest = HTCAPTION ) return; CFrameWnd:OnNcLButtonDown(nHitTest, point); BOO
7、L SetWindowPos(HWND hWnd, /窗口句柄HWND hWndInsertAfter, /排列顺序的句柄int X, /水平坐标int Y, /垂直坐标int cx, /宽int cy, /高UINT uFlags /窗口定位标识); 说明:这个函数能改变窗口的大小、位置和设置子窗口、弹出窗口或顶层窗口的排列顺序。 返回值:BOOL,如果返回值非零表示成功,返回零表示失败。错误信息请参看GetLastError函数。参数表:hWnd:欲定位的窗口句柄 hWndInsertAfter:置于hWnd前面的窗口句柄。这个参数必须是窗口的句柄或是下面的值之一: HWND_BOTTOM
8、 将窗口置于其它所有窗口的底部 HWND_NOTOPMOST 将窗口置于其它所有窗口的顶部,并位于任何最顶部窗口的后面。如果这个窗口非顶部窗口,这个标记对该窗口并不产生影响 HWND_TOP 将窗口置于它所有窗口的顶部 HWND_TOPMOST 将窗口置于其它所有窗口的顶部,并位于任何最顶部窗口的前面。即使这个窗口不是活动窗口,也维持最顶部状态 x:指定窗口新的X坐标Y:指定窗口新的Y坐标 cx:指定窗口新的宽度 cy:指定窗口新的高度 wFlags:UINT,指定窗口状态和位置的标记。这个参数使用下面值的组合: SWP_DRAWFRAME 围绕窗口画一个框 SWP_FRAMECHANGED
9、发送一条WM_NCCALCSIZE消息进入窗口,即使窗口的大小没有发生改变。如果不指定这个参数,消息WM_NCCALCSIZE只有在窗口大小发生改变时才发送 SWP_HIDEWINDOW 隐藏窗口 SWP_NOACTIVATE 不激活窗口 SWP_NOCOPYBITS 屏蔽客户区域 SWP_NOMOVE 保持当前位置(X和Y参数将被忽略) SWP_NOOWNERZORDER 不改变所有窗口的位置和排列顺序 SWP_NOREDRAW 窗口不自动重画 SWP_NOREPOSITION 与SWP_NOOWNERZORDER标记相同 SWP_NOSENDCHANGING 防止这个窗口接受WM_WIND
10、OWPOSCHANGING消息 SWP_NOSIZE 保持当前大小(cx和cy会被忽略) SWP_NOZORDER 保持窗口在列表的当前位置(hWndInsertAfter将被忽略) SWP_SHOWWINDOW 显示窗口 备注:如果设置了SWP_SHOWWINDOW或SWP_HIDEWINDOW标记,这个窗口不发生移动或改变大小。窗口成为最顶级窗口后,它的所有子窗口也会进入最顶级。一旦将其设为非最顶级,则它的所有子窗口也会转为非最顶级设置对话框背景方法一:调用CWinApp类的成员函数SetDialogBkColor来实现。 - 其中函数的第一个参数指定了背景颜色,第二个参数指定了文本颜色。
11、 下面的例子是将应用程序对话框设置为蓝色背景和红色文本,步骤如下: - 新建一个基于Dialog的MFC AppWizard应用程序ExampleDlg。 - 在CExampleDlgApp :InitInstance()中添加如下代码: BOOL CExampleDlgApp: : InitInstance ( ) CExampleDlgDlg dlg; m_pMainWnd = &dlg; /先于DoModal()调用,将对话框设置为蓝色背景、红色文本 SetDialogBkColor(RGB(0,0,255),RGB(255,0,0); int nResponse = dlg.DoMod
12、al(); - 编译并运行,此时对话框的背景色和文本色已发生了改变。值得注意的 是:在调用DoModal()之前必须先调用SetDialogBkColor,且此方法是将改变 应用程序中所有的对话框颜色,并不能针对某一个指定的对话框。 方法二:重载OnPaint(),即WM_PAINT消息。有关代码如下(以上例工程为准): void CExampleDlgDlg:OnPaint() if (IsIconic() else CRect rect; CPaintDC dc(this); GetClientRect(rect); dc.FillSolidRect(rect,RGB(0,255,0);
13、/设置为绿色背景 CDialog:OnPaint(); 方法三:重载OnCtlColor (CDC* pDC, CWnd* pWnd, UINT nCtlColor), 即WM_CTLCOLOR消息。具体步骤如下(以上例工程为准): - 在CExampleDlgDlg的头文件中,添加一CBrush的成员变量: class CExampleDlgDlg : public CDialog . protected: CBrush m_brush; . ; - 在OnInitDialog()函数中添加如下代码: BOOL CExampleDlgDlg:OnInitDialog() . / TODO:
14、Add extra initialization here m_brush.CreateSolidBrush(RGB(0, 255, 0); / 生成一绿色刷子 . - 利用ClassWizard重载OnCtlColor(),即WM_CTLCOLOR消息: HBRUSH CExampleDlgDlg:OnCtlColor (CDC* pDC, CWnd* pWnd, UINT nCtlColor) /* * 这里不必编写任何代码! *下行代码要注释掉 * HBRUSH hbr = CDialog:OnCtlColor(pDC, pWnd, nCtlColor); */ return m_bru
15、sh; /返加绿色刷子 方法四:还是重载OnCtlColor (CDC* pDC, CWnd* pWnd, UINT nCtlColor), 即WM_CTLCOLOR消息。具体步骤如下(以上例工程为准): - 步骤、同上方法三中的步骤、。 - 步骤利用ClassWizard重载OnCtlColor()(即WM_CTLCOLOR消息)时则有 些不同: HBRUSH CExampleDlgDlg:OnCtlColor (CDC* pDC, CWnd* pWnd, UINT nCtlColor) HBRUSH hbr = CDialog:OnCtlColor(pDC, pWnd, nCtlColor
16、); /在这加一条是否为对话框的判断语句 if(nCtlColor =CTLCOLOR_DLG) return m_brush; /返加绿色刷子 return hbr; 1:如何修改单文档应用程序的窗口标题,查阅MSDC文章:Changing the styles of a window created by MFC. 要在CMainFrame的PrecreatWindow()中加入如下代码: cs.style&=FWS_ADDTOTITLE; cs.lpszName=This is a test!; 可以先不要上一句试一试!另一种方法是 : cs.style=WS_OVERLAPPEDWIN
17、DOW;再进行修改,也可以不修改,那么是去掉默认文档标题,而只显示原程序标题! 另一类方法是在窗口创建后再修改,因为在OnCreate中,开始的这些代码: if (CFrameWnd:OnCreate(lpCreateStruct) = -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) | !m_wndToolBar.LoadT
18、oolBar (IDR_MAINFRAME) TRACE0(Failed to create toolbarn); return -1; / fail to create if (!m_wndStatusBar.Create(this) | ! m_wndStatusBar.SetIndicators(indicators, sizeof (indicators)/sizeof(UINT) TRACE0(Failed to create status barn); return -1; / fail to create / TODO: Delete these three lines if y
19、ou dont want the toolbar to / be dockable m_wndToolBar.EnableDocking (CBRS_ALIGN_ANY); EnableDocking (CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar);完成了窗口创建,工具栏,状态栏的创建等工作,可以在后面利用一个系统全局函数SetWindowLong()函数进行修改:加入代码为:SetWindowLong(m_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW);与此相对,还有一个GetWindowLong()函数可供使用!如下面
20、代码去掉了窗口上的最大化按钮:SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE) & MAXIMIZEBOX);当然SetWindowLon()还可以做别的修改.与SetWindowLong()相类似的另一个系统全局函数为 SetClassLong();2:如何完成一个动画图标其实就是准备好几个图标,在定时器消息 响应中更改图标即可完成.第一步是准备好几个(如三个)图标.第二步是在CMainFrame类中做三个图标类的相关对象的成员变量,或者是一个大小为3的HICON数组.第三步是在CMainFrame类的OnCreat
21、e()函数中LoadIcon()进行对三个图标的加载.其中用到的实例句柄的获取有三种方法:一:用全局函数AfxGetInstanceHandle()获取,二:先在CMainFrame类中用extern声明一下全局对象theApp,然后使用theApp.hInstance;三:使用全局函数AfxGetApp()获取全局对象theApp对象的指针,然后用AfxGetApp()-hInstance;第二个参数是一个字符指针,可我们只有图标的资源ID,所以要进行必要的转换:用MAKEINTRESOURCE宏!第四步是设置定时器,也在OnCreate()函数中定义:SetTimer(1,1000,NUL
22、L);第五步是在CMainFrame中添加WM_TIMER消息响应,在其中加入代码: static int index=0; SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIconsindex); index=+index%3;3:在工具栏上新加一个按钮,要让它与前一个按钮之间有一个分隔符,只需要将它轻轻向一旁拖动一点点再放开即可,而要删除工具栏上的一个按钮,你只是选中它再按DEL键是完不成的,它只是将按钮上的图案删除,所以删除一个按钮要将它拖动到工具栏之外,再松手!4:如何创建一个工具栏在MSDN的关于CToolBar的讲解页有详细说明!一:插入工具栏资源,二
23、:在CMainFrame中加入一个CToolBar类对象的成员变量,三:在CMainFrame的OnCreate()中加入: if (!m_MyToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) | ! m_MyToolBar.LoadToolBar(IDR_MYTOOLBAR) TRACE0(Failed to create toolbarn); return -1; / fa
24、il to create m_MyToolBar.EnableDocking (CBRS_ALIGN_ANY); DockControlBar(&m_MyToolBar);各个函数调用及参数传递查看MSDN!5:如何让一个工具栏隐藏或显示: if(m_MyToolBar.IsWindowVisible() m_MyToolBar.ShowWindow(SW_HIDE); else m_MyToolBar.ShowWindow(SW_SHOW); 但这样做的结果是工具栏虽说隐藏了, 但是工具条还在,所以还要在后面加上一句: ReCalcLayout();这样做还是有问题,如果工具栏没有停靠在边上
25、而是一个单独的小窗口,那么只做上面的工作只使得工具栏上的按钮不见了,而那个小窗口还在,所以,还要调用一个函数: DockControlBar (&m_MyToolBar);经过上面这句,小窗口也如愿消失了,但问题还有一点,就是当用户将工具栏放置为一个小窗口时,再点击菜单,要让这个工具栏显示出来,当然我们应该将工具栏仍按用户先前的小窗口样式显示出来比较好,可是这次工具栏又自动停靠在客户区顶部了?这个功能如何实现呢?孙老师只是提示可以查MSDN中CToolBar的成员函数解决这个问题,并没细讲,所以我看了MSDN,发现有两个函数:CToolBar:IsFloating()利用这个函数可以判断一个工
26、具栏是否处于浮动状态,另一个是CFrameWnd:FloatControlBar()这个函数可以让一个控制栏处于浮动状态,然后我在CMainFrame中加入了一个BOOL型的成员变量,在每次判断工具栏是否可见时用来记录工具栏是否处于浮动状态,然后在重新生成工具栏时根据它的置决定是否将工具栏设为浮动状态,但是第二个函数好像不太好使,所以我又换用了SetWindowPos()成员函数,可是也不能将它放置为一个独立的小窗口. 显示和隐藏工具栏的第二种方法:用一个函数:CFrameWnd:ShowControlBar(),因为这个函数的固有特性,上面是if.else.判断就可以简化为一句代码: Sho
27、wControlBar(&m_MyToolBar,!m_MyToolBar.IsWindowVisible(),FALSE);并且我惊讶的发现,用这个函数时,上面提到的浮动工具栏让它在恢复的时候仍回复为浮动的问题自动解决了!哈哈,好.6:状态栏相关编程因为MFC自动生成的系统已经包含了一个状态栏,所以我们暂时仅限于已有状态栏的修改,而不是另外生成一个状态栏.状态栏最左边的那一长条,就是经常显示一些提示字符串的那部分叫做提示行,而右侧那三个小窗口是用来指示 CapsLock,ScrollLock,NumLock开关的状态,称为状态指示器.状态栏跟工具栏一样,也是在CMainFrame类中定义并在
28、OnCreate()中创建的.下面的代码在状态指示器的最左边放置了两个小窗口,并在第一个小窗口中放置了一个时钟:同样的CMainFrame的OnCreate() 中, CTime tm=CTime:GetCurrentTime(); CString strTime=tm.Format(%H:%M:%S); CClientDC dc(this); CSize sz=dc.GetTextExtent(strTime); m_wndStatusBar.SetPaneInfo (1,IDS_TIMER,SBPS_NORMAL,sz.cx);/调整窗口大小 m_wndStatusBar.SetPaneT
29、ext(1,strTime); SetTimer(2,1000,NULL);当然要先有准备工作,在字符串资源中添加两个字符串,ID分别为:IDS_TIMER,IDS_PROGRESS,交将之添加到MainFrm.cpp的static UINT indicators = ID_SEPARATOR, / status line indicator IDS_TIMER, IDS_PROGRESS, ID_INDICATOR_CAP S, ID_INDICATOR_NUM, ID_INDICATOR_SCRL,;这个数组中,并且上面SetPaneInfo()中的第一个参数就是相应ID在indicato
30、rs数组中的索引值,显然最后三个ID是大小写,数字锁及ScroolLock的标识.做完上面这些工作,这个时钟还不能变化,只是显示了一个定值,我们还要在定时器的响应函数中再刷新该值: if (2=nIDEvent) CTime tm=CTime:GetCurrentTime(); CString strTime=tm.Format(%H:%M:%S); m_wndStatusBar.SetPaneText (1,strTime); 这样就完成了一个在状态栏中显示的,可以动态变化的时钟!7:如何创建一个进度条并将之放置在状态栏中的某个位置?与MFC中其它标准资源一样,进度条也有一个专门的类与之相对
31、应:CProgressCtrl类.先在CMainFrame中放置一个成员变量:CProgressCtrl m_ProgBar;然后在OnCreate()中加 入: m_ProgBar.Create(WS_CHILD | WS_VISIBLE,CRect (300,100,500,120),this,88888);就可以在窗口中显示一个进度条.至于要将之放置于状态栏上的某个窗格之中,就要先得到窗格所在的矩形区域,然后在上面是第二个参数中进行指定,故将上面一句改为如下: CRect rect; m_wndStatusBar.GetItemRect (2,&rect); m_ProgBar.Crea
32、te(WS_CHILD | WS_VISIBLE,rect,this,88888);可是这样并未实现设置,所以我们在上面设置断点,发现到达m_ProgBar.Create()时矩形区域的值并不正常,原来在OnCreate()未结束时,状态栏的设置无法完成,无法获得矩形区域位置,所以,就要想办法在OnCreate()结束时做上面的工作,可以做一个自定义消息,在OnCreate()末尾发送一个该消息,并做一个消息响应函数,然后将上面的代码放置在其中即可.要自定义消息,首先要在CMainFrame的头文件首部 做: #define UM_PROGRESS WM_USER+1 /注意,没有;WM_US
33、ER是一个系统定义宏,详细情况查MSDN.然后在CMainFrame的头文件的消息响应中加入消息响应函数的声明: afx_msg void OnProgress();再加入消息映射: ON_MESSAGE(UM_PROGRESS,OnProgress)再实现消息响应函数:void CMainFrame:OnProgress() CRect rect; m_wndStatusBar.GetItemRect(2,&rect); m_ProgBar.Create(WS_CHILD | WS_VISIBLE,rect,&m_wndStatusBar,123);/注意,这里父窗口就不能设置为this了,
34、 而要是状态栏! m_ProgBar.SetPos(50);当然,不能忘了在OnCreate()最 后发送消息: PostMessage(UM_PROGRESS);这样就可以了!但是问题还是有的,你会发现当你拉动窗口改变其大小时,状态栏的位置发生了变化,不再覆盖在先关状态栏的那个小窗口上了,怎么办呢?你会想到在窗口大小改变时,系统会接受到一个WM_PAINT消息,只要在那个消息的响应函数中实时获取小窗口的矩形区域,再改变进度条的位置,不就可以了吧,没错,这样的确可以,又因为WM_PAINT消息当窗口显示时,也就是说OnCreate()之后就会马上收到,所以我们也不用像上面那样麻烦的自定义什么消
35、息啦,直接在CMainFrame中加入WM_PAINT的消息响应函数,并在其中加入: CRect rect; m_wndStatusBar.GetItemRect(2,&rect); m_ProgBar.Create(WS_CHILD | WS_VISIBLE,rect,&m_wndStatusBar,123); m_ProgBar.SetPos(50);即可了,但是问题又来了,当窗口大小一改变时,程序发生了一个致使错误,原来我们不能在每一次响应时都创建进度条,进度条对象只有一个,哪能多次使用呢?所以,改为如下代码: CRect rect; m_wndStatusBar.GetItemRect
36、(2,&rect); if(!m_ProgBar.m_hWnd) m_ProgBar.Create(WS_CHILD | WS_VISIBLE,rect,&m_wndStatusBar,88888); else m_ProgBar.MoveWindow(&rect); m_ProgBar.SetPos(50);这下,无论怎么拖,也不会发生异常现象了!那么,如何让进度条动起来呢?相关的成员函数为SetStep(),以及StepIt();8:下面的代码将鼠标当前的位置坐标显示在状态栏的提示行中:在View类中响应WM_MOUSEMOVE消息,在其中加入代码如下: CString str; str.
37、Format(x=%d,y=% d,point.x,point.y); (CMainFrame*)GetParent()-m_wndStatusBar.SetWindowText(str);这段代码要正常运行的前提是首先CMainFrame在View文件中不可见,所以要先包含一个MainFrm.h头文件,然后,因为m_wndStatusBar在CMainFrame中是一个protected变量,所以不能在View类中访问,所以我们要手动把它的访问权限改为public.然后就OK了!其实还有一种更方便的方法:调用CFrameWnd:SetMessageText()所以上面的代码就 可以改为: C
38、String str; str.Format(x=%d,y=% d,point.x,point.y); (CMainFrame*)GetParent()-SetMessageText (str);这样子,就不用取得状态栏指针了,也就不用去修改其访问权限了!关于这个工作,还有第三种方法,也不用去修改状态栏的访问权限,这是应用了另一个函数:CHtmlView:GetStatusBar(),上面的代码就可以是: CString str; str.Format(x=%d,y=%d,point.x,point.y); (CMainFrame*)GetParent()-GetMessageBar()-Se
39、tWindowText(str);下面还有第四种方式:这是应用了又一个函数:CWnd:GetDescendantWindow(),这个函数可以根据窗口ID来从调用它的窗口出发找到与该ID相同的一个子孙窗口的指针: CString str; str.Format(x=%d,y=%d,point.x,point.y); GetParent()-GetDescendantWindow(AFX_IDW_STATUS_BAR)-SetWindowText(str);至于上面那个ID号,是从CStatusBar:Create()中看到它!关于GetDescendantWindow()的调用,要注意其第二个
40、参数在MSDN中关于临时窗口及持久窗口的讲解!9:关于程序的启动画面的制作这个跟往程序中加入右键PopUp菜单一样,可以使用VC的组件库中的组件.找到一个叫SplashScreen的东西,加入它到工程中,别的什么也别动,先编译运行一下,你会发现程序已经有一个启动画面了,不过是很简陋的.这个组件在我们的程序中加入了一副默认位图,并加入了一个叫CSplashWnd的类,并且在CMainFrame的OnCreate()函数中加入了一句:CSplashWnd:ShowSplashScreen(this),进行了相应的启动工作.在CSplashWnd的成员函数OnCreate()中有一句SetTimer(1, 750, NULL);其消息响应函数中进行了启动画面的隐藏,所以,修改其中的时间值可以修改启动画面显示的时间长度!另外,可以发现窗口的显示与启动画面的显示是同时进行的,如何才能让画面消失时窗口才显示出来呢?至于启动画面的改变,可以自己插入位图,然后将它的ID修改为IDB_SPLASH 然后RebuildAll,也可以在其源文件中LoadBitmap()中将ID改为自己想要加载的位图的ID!