huzunbo
|
21. 介绍函数过程中一种任意键退出同时能处理消息的实现方法 1. 设置定时器,用于使::GetMessage(...)函数总能快速取到消息. 2. 在函数处理中加入: 函数每执行完一步后执行下面的代码. if (::GetMessage(&msg, 0, 0, 0)) { if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) return ; ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else ::PostQuitMessage(0); 22. 如何隐藏工具栏 添加如下两个函数 隐藏: void CMainFrame::OnHide() { if(m_wndToolBar.IsWindowVisible()) m_wndToolBar.ModifyStyle(WS_VISIBLE,0); SendMessage(WM_SIZE); } 显示: void CMainFrame::OnShow() { if(!m_wndToolBar.IsWindowVisible()) m_wndToolBar.ModifyStyle(0,WS_VISIBLE); SendMessage(WM_SIZE); } 23. 如何动态获取工具条指针并给工具条加标题? [问题提出] 工具条也是窗口,是窗口就有标题,如何给工具条加标题? [程序实现] 不想动态改变工具条的标题就在CMainFrame::OnCreate()中: int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { ...... m_wndToolBar.SetWindowText(_T("Standdard")); return 0; } 若想动态改变工具条的标题,如下: 声明一个菜单,并响应事件,如响应:OnMyToolBar()函数 void CMainFrame::OnMyToolBar() { // TODO: Add your command handler code here CToolBar *pToolBar = (CToolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR); pToolBar->SetWindowText (_T("Standdard")); } 不要在TooBar悬浮时做OnMyToolBar()会出错的. 顺便提一下如何获得状态条的指针: CStatusBar * pStatusBar =(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR); 24. 在状态条中显示鼠标的设备坐标与逻辑坐标 显示器的设备坐标系的原点在客户区的左上角,x轴向右增长,y轴向下增长。我们要设置的逻辑坐标系的原点则在客户区的中心,x轴向右增长,y轴向上增长,如一个笛卡尔坐标系一般。 为CChildView添加一个成员函数void OnPrepareDC(CDC * pDC, CPrintInfo * pInfo = NULL); void OnPrepareDC(CDC * pDC, CPrintInfo * pInfo){ CRect rect; // 设置映射模式为LOMETRIC (0.1mm),右上为增长方向 pDC->SetMapMode (MM_LOMETRIC); // 将坐标原点定在客户区的中心 GetClientRect(rect); pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2); } 为CChildView响应鼠标移动消息,并在状态条中显示鼠标的坐标值。m_ptMouse数据成员是原打算做十字交叉线用的,在此使用没有实际意义。 void CChildView::OnMouseMove(UINT nFlags, CPoint point){ CClientDC dc(this); CString str; OnPrepareDC(&dc); //要访问类CMainFrame,需要将mainfrm.h文件引入 CMainFrame * pFrame = (CMainFrame *) AfxGetApp()->m_pMainWnd; //要访问CMainFrame的数据成员m_wndStatusBar,需要手工修改mainfrm.h,public这个数据成员 CStatusBar * pStatus = (CStatusBar *) &pFrame->m_wndStatusBar; m_ptMouse = point; str.Format ("设备坐标 X=%i pixel, Y=%i pixel", m_ptMouse.x, m_ptMouse.y); pStatus->SetPaneText(1, str); dc.DPtoLP(&m_ptMouse); str.Format ("逻辑坐标 X=%i * 0.1mm, Y=%i * 0.1mm", m_ptMouse.x, m_ptMouse.y); pStatus->SetPaneText(2, str); } 25. 如何用VC++ 动态修改应用程序菜单 [问题提出] 本文将介绍一些使用CMenu的方法,如查找指定菜单,在指定选项前添加菜单项..... [解决方法] 使用CWnd::GetMenu( )访问主菜单,GetMenu( )返回指向CMenu对象的指针,它有一些成员函数,允许我们修改一个菜单。 1) 如何实现找到一个菜单项: 步骤如下: { //动态修改菜单: // Get the Main Menu CMenu* pMainMenu = AfxGetMainWnd()->GetMenu(); CMenu* pSubMenu = NULL; int i; for (i=0; i<(int)pMainMenu->GetMenuItemCount(); i++) { pSubMenu = pMainMenu->GetSubMenu(i); if (pSubMenu && pSubMenu->GetMenuItemID(0) == ID_FILE_NEW) break; } CString s; s.Format("%d",i);//菜单项的位数. AfxMessageBox(s); ASSERT(pSubMenu); } 2) 动态编辑菜单: 步骤如下(可以用上例的pSubMenu,要加的菜单你自己定义.): 1) 添加一个称为Wzd2,命令ID为IDC_NAME_NEW1的菜单命令到该菜单中,可以用: pSubMenu->AppendMenu(0,IDC_NAME_NEW1,"New&1"); 2) 在New1前插入New2,可以用: pSubMenu->InsertMenu(IDC_NAME_NEW1,MF_BYCOMMAND,IDC_NAME_NEW2, "New&2"); 3) 把New1改变成New3,可以用: pSubMenu->ModifyMenu(IDC_NAME_NEW1,MF_BYCOMMAND,IDC_NAME_NEW3, "New&3"); 4) 删除该菜单中第二项,可以用: pSubMenu->RemoveMenu(1,MF_BYPOSITION); 26. VC++中的3D按钮的编程 运行AppWizard生成一个基于对话框的test工程,在对话框中加入一个CButton控件。在CButton控件的General属性页将控件的ID改为IDC_3DTEXTBTN,Caption改为“谁与争疯”,在控件Styles属性页选中OwnerDraw,其余设置保持默认。 用classwizard创建一个新类:C3dTextButton,基类为CButton。为C3dTextButton类添加一个protected的函数void Draw(CDC* pDC, const CRect& rect, UINT state)。如下所示编写代码: void C3dTextButton::Draw(CDC *pDC, const CRect &rect, UINT state) { CString text; GetWindowText(text); int l=text.GetLength(); CRect rectClient=rect; //获得控件的字体 CFont* pFont=GetFont(); //确定所选字体有效高度和宽度 LOGFONT logfont; pFont->GetObject(sizeof(LOGFONT),&logfont); if(logfont.lfHeight==0)logfont.lfHeight=20; logfont.lfWidth=0;//宽度设为0,宽度值由高度确定 logfont.lfWeight=1000; logfont.lfEscapement=logfont.lfOrientation=0; CFont tryfont; VERIFY(tryfont.CreateFontIndirect(&logfont)); CFont* pFontOld=pDC->SelectObject(&tryfont); //根据控件大小,调整字体的高度,使文本与控件协调 CSize textSizeClient=pDC->GetTextExtent(text,l); if(rectClient.Width()*textSizeClient.cy>rectClient.Height()*textSizeClient.cx) { logfont.lfHeight=::MulDiv(logfont.lfHeight,rectClient.Height(),textSizeClient.cy); } else{ logfont.lfHeight = ::MulDiv(logfont.lfHeight,rectClient.Width(),textSizeClient.cx); } //创建并选择协调后的字体 CFont font; font.CreateFontIndirect(&logfont); pDC->SelectObject(&font); textSizeClient=pDC->GetTextExtent(text,l); //确定文本与控件边界的距离minx,miny int minx=rectClient.left+(rectClient.Width()-textSizeClient.cx)/2; int miny=rectClient.top+(rectClient.Height()-textSizeClient.cy)/2; int oldBkMode=pDC->SetBkMode(TRANSPARENT); COLORREF textcol=::GetSysColor(COLOR_BTNTEXT); COLORREF oldTextColor=pDC->SetTextColor(textcol); int cx = minx; int cy = miny; int s=(state&ODS_SELECTED)?-1:+1; cx+= 3; cy+= 3; //实现3D效果 pDC->SetTextColor(::GetSysColor(COLOR_3DDKSHADOW)); pDC->TextOut(cx-s*2,cy+s*2,text); pDC->TextOut(cx+s*2,cy-s*2,text); pDC->TextOut(cx+s*2,cy+s*2,text); pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT)); pDC->TextOut(cx+s*1,cy-s*2,text); pDC->TextOut(cx-s*2,cy+s*1,text); pDC->TextOut(cx-s*2,cy-s*2,text); pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW)); pDC->TextOut(cx-s*1,cy+s*1,text); pDC->TextOut(cx+s*1,cy-s*1,text); pDC->TextOut(cx+s*1,cy+s*1,text); pDC->SetTextColor(::GetSysColor(COLOR_3DLIGHT)); pDC->TextOut(cx,cy-s*1,text); pDC->TextOut(cx-s*1,cy,text); pDC->TextOut(cx-s*1,cy-s*1,text); pDC->SetTextColor(textcol); //输出标题 pDC->TextOut(cx,cy,text); //恢复设备描述表 pDC->SetTextColor(oldTextColor); pDC->SetBkMode(oldBkMode); pDC->SelectObject(pFontOld); } 用classwizard重载C3dTextButton类的DrawItem函数。编写代码如下所示: void C3dTextButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC* pDC=CDC::FromHandle(lpDrawItemStruct->hDC); ASSERT_VALID(pDC); CRect rectClient=lpDrawItemStruct->rcItem; Draw(pDC,rectClient,lpDrawItemStruct->itemState); } 用classwizard为IDC_3DTEXTBTN建立一个C3dTextButton控件变量m_3dTextButton1。 把“3dTextButton.h”加入testDlg头文件。编译并测试应用程序。 27. 如何正确的得到ComBox的指针 CComboBox *mComb = (CComboBox*)GetDlgItem(IDC_DuanCB); CComboBox *mComb = (CComboBox*)::GetDlgItem(m_hWnd,IDC_DuanCB); 28. 如何让对话框中的CEdit控件类接收对话框的消息 //////////////////////////////////////////////// // 如何让对话框中的CEdit控件类接收对话框的消息 //////////////////////////////////////////////// 1、在对话框中增加一个ID 为IDC_EDIT1的CEdit1控件 2、通过ClassWizard 生成一个基于CEdit的新类CMyEdit, CMyEdit m_wndEdit; 3、在对话框OnInitDialog()中,将m_wndEdit子类化,使其能够接受对话框的消息。 m_wndEdit.SubclassDlgItem (IDC_EDIT1,this); 29.利用WM_CTLCOLOR消息实现编辑控制(Edit Control)的文本与背景色的改变 首先要明白:WM_CTLCOLOR是一个由控制(Control)发送给它父窗口的通知消息(Notification message)。 实现步骤: 生成一个标准的单文档应用程序框架,假设应用程序的名称为Color。我将利用它的About对话框做示范。在About dialog中添加两个Edit control,设定其ID为IDC_EDIT1与IDC_EDIT2。 第一种方法(对应于IDC_EDIT1): 按照标准的Windows编程,由其父窗口的消息处理函数负责处理WM_CTLCOLOR消息。 1. 在CAboutDlg中添加一个数据成员:HBRUSH m_brMine; 2. 利用向导映射AboutDlg的WM_CTLCOLOR消息,产生函数:HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); pDC是AboutDlg的设备上下文,pWnd是AboutDlg中发送该消息的control指针,nCtlColor市Control的类型编码。对其进行如下修改: HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if ((pWnd->GetDlgCtrlID() == IDC_EDIT1) && (nCtlColor == CTLCOLOR_EDIT)) { COLORREF clr = RGB(255,0,0); pDC->SetTextColor(clr); //设置红色的文本 clr = RGB(0,0,0); pDC->SetBkColor(clr); //设置黑色的背景 m_brMine = ::CreateSolidBrush(clr); return m_brMine; //作为约定,返回背景色对应的刷子句柄 } else { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); return hbr; } } 第二种方法(对应于IDC_EDIT2): 利用MFC 4.0的新特性: Message reflection。 1.利用向导添加一个新的类:CColorEdit,基类为CEdit; 2.在CColorEdit中添加一个数据成员: HBRUSH m_bkBrush; 3.利用向导映射CColorEdit的"=WM_CTLCOLOR"消息,产生函数: HBRUSH CColorEdit::CtlColor(CDC* pDC, UINT nCtlColor); 对其进行如下修改: HBRUSH CColorEdit::CtlColor(CDC* pDC, UINT nCtlColor) { COLORREF clr = RGB(0,0,0); pDC->SetTextColor(clr); //设置黑色的文本 clr = RGB(255,0,0); pDC->SetBkColor(clr); //设置红色的背景 m_bkBrush = ::CreateSolidBrush(clr); return m_bkBrush; //作为约定,返回背景色对应的刷子句柄 } 4.利用向导为IDC_EDIT2生成一个数据成员CColorEdit m_coloredit; 5.在定义CAboutDlg的color.cpp文件中加入:#include "coloredit.h" 30. 如何防止密码被非法获取? [问题提出] 这两天大家比较专注在获取Edit密码框的密码.在盗取时,我们如何防范呢? [解决方法] 此方法针对于通过SendMessage向此窗口发送WM_GETTEXT或EM_GETLINE消息来取得密码.跟我来. [程序实现] 方法很简单,用CWnd::DefWindowProc函数拦截得到的消息(向Edit发的). 建立名为My的对话框工程.建立一个Edit控件ID=IDC_EDIT1.建一个新类名为CMyProtectEdit,派生于CEdit. 在MyDlg.cpp中声明全局变量:BOOL g_bIdentity; BOOL g_bIdentity; 在MyProtecEdit.cpp中: extern BOOL g_bIdentity; 响应CMyProtectEdit的DefWindowProc函数: LRESULT CMyProtectEdit::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // TODO: Add your specialized code here and/or call the base class // 对Edit的内容获取必须通过以下两个消息之一,不对其采用默认的处理: if(( message == WM_GETTEXT) || ( message == EM_GETLINE)) { //检查是否为合法 if(!g_bIdentity) { //非法获取,显示非法信息 AfxMessageBox(_T("不能让你看我的密码,:( !")); return 0; ) g_bIdentity = FALSE;//合法获取 } return CEdit::DefWindowProc(message, wParam, lParam); } 然后在MyDlg.cpp中 void CMyDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CGetPasswordDlg) // NOTE: the ClassWizard will add DDX and DDV calls here if( pDX->m_bSaveAndValidate) { g_bIdentity = TRUE; } //}}AFX_DATA_MAP } 即可.找个程序(盗取)的试试. |
2006-10-8 15:55:13 | |
huzunbo
|
31. 如何在编辑控件中以追加的方式添入字符? [问题提出] SetDlgItemText可以向Edit控件中输入字符,发送更新的消息也可是Edit控件显示与其关联的变量的值,但若是向已有的Edit字符后追加字符,该如何做? [程序实现] 建立名为My的对话框工程,添加一个Edit和一个Button控件.Edit的ID=IDC_EDIT1,Button的ID=IDC_BUTTON1.建立和IDC_BUTTON1的响应函数:OnButton1() void CMyDlg::OnButton1() { CString pText="你好"; CEdit *m_Edit=(CEdit *)GetDlgItem(IDC_EDIT1); int nLen=m_Edit->GetWindowTextLength(); m_Edit->SetFocus(); m_Edit->SetSel(nLen, nLen); m_Edit->ReplaceSel(pText); } 在Edit控件中输入字符,想追加时按IDC_BUTTON1按钮.看看效果. 32.属性页标题改名 我用CPropertySheet创建属性页,用的CPropertyPage对象只有一个,也就是每个属性页的内容一样.现在的问题是:这样每个属性页的标题都是一样的,是对话框的标题!怎样动态的改变这个标题,使每个属性页的标签的名称都不同?? CTabCtrl * pCtrl = pSheet->GetTabControl(); TCITEM tc; tc.mask = TCIF_TEXT; tc.pszText = "新标题"; pCtrl->SetItem(0,&tc);//0即是你要改的TAb的索引 33. 怎样去掉属性页的Apply与Help按钮? //去掉Help m_psh.dwFlags |= PSH_HASHELP ; m_psh.dwFlags &= ~PSH_HASHELP ; //除掉应用按钮 m_psh.dwFlags|=PSH_NOAPPLYNOW; 34. 如何给树控件加入工具提示 1.首先给树控件加入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; } 2.其次加入映射消息声明,如下所示: afx_msg void OnGetInfoTip(NMHDR* pNMHDR,LRESULT* pResult); //树控件上加入提示消息,jingzhou xu ON_NOTIFY(TVN_GETINFOTIP, 100, OnGetInfoTip) //树控件条目上加入提示,jingzhou xu 3.最后加入呼应涵数处理: 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); } 35. 如何在TreeList中加图标? [问题提出] 请问treeview控件和treectrl控件的用法有何不同呢?向如何imagelist控件中加图象呀? [解决方法] 1) HICON hicon[8]; m_imageList.Create(16,16,0,8,8); hicon[0]=AfxGetApp()->LoadIcon(IDI_ICON0); hicon[1]=AfxGetApp()->LoadIcon(IDI_ICON1); hicon[2]=AfxGetApp()->LoadIcon(IDI_ICON2); hicon[3]=AfxGetApp()->LoadIcon(IDI_ICON3); hicon[4]=AfxGetApp()->LoadIcon(IDI_ICON4); hicon[5]=AfxGetApp()->LoadIcon(IDI_ICON5); hicon[6]=AfxGetApp()->LoadIcon(IDI_ICON6); hicon[7]=AfxGetApp()->LoadIcon(IDI_ICON7); for(int n=0;n<8;n++) m_imageList.Add(hicon[n]); CTreeCtrl *pTree=(CTreeCtrl *)GetDlgItem(IDC_TREE); pTree->SetImageList(&m_imageList,TVSIL_NORMAL); 2) CImageList cil1; cil1.Create(32,32,TRUE,2,2); cil1.Add(pApp->LoadIcon(IDI_DAO1)); cil1.Add(pApp->LoadIcon(IDI_DAO2)); cil1.Add(pApp->LoadIcon(IDI_DAO3)); cil1.Add(pApp->LoadIcon(IDI_DAO4)); cil1.Add(pApp->LoadIcon(IDI_DAO5)); cil1.Add(pApp->LoadIcon(IDI_DAO6)); cil1.Add(pApp->LoadIcon(IDI_DAO7)); cil1.Add(pApp->LoadIcon(IDI_DAO8)); cil1.Add(pApp->LoadIcon(IDI_DAO9)); //设置图象列表 m_list.SetImageList(&cil1,LVSIL_NORMAL); 36. 如何双击列表框项启动一个与文件关联的程序? 有人问我如何双击列表框项启动一个程序?其实这个问题很简单,Windows中有一个API函数可以打开任何类型的文件: ShellExecute(NULL,"open",lpFileName,NULL,NULL,SW_SHOWNORMAL); 参数 lpFileName 是文件的全路径名。用这个变量你可以传递象“C:\\MyExcelFile.xls”或者“http://www.vckbase.com”启动Excel程序或者浏览器程序。如果你只是想获取与文件关联的程序名,而不是要运行程序,那么调用::FindExecutable就可以了。 37. 如何防止在listbox中添加很多数据出现不停的刷新? [问题提出] 在listbox添加很多数据的时候,由于控件不停的刷新,导致出现闪烁,如何解决? [解决方法] 再添加数据以前,禁止控件刷新,数据添加完毕以后,再刷新一次。 [程序实现](其中:m_ListBox是CListBox的控件类型的变量) m_ListBox.LockWindowUpdate();//禁止本listbox刷新。 for(int i=0;i<9999;i++) { m_ListBox.AddString("test"); }//添加数据。 this->RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); 38. 如何得到CListBox所选择项的String? [问题提出] 如何得到CListBox所选择项的String [解决方法] 用到:CListBox::GetText() [程序实现] CString scInfo; pList->GetText( GetCurSel(),scInfo); 39. 用鼠标移动基于对话框的无标题栏程序的简单方法 void CVCTestDlg::OnLButtonDown(UINT nFlags, CPoint point) { //一句话解决问题 SendMessage(WM_SYSCOMMAND,0xF012,0); CDialog::OnLButtonDown(nFlags, point); } 40. 如何改变框对话或窗体视窗的背景颜色 调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。 BOOL CSampleApp : : InitInstance ( ) { … //use blue dialog with yellow text . SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 , 255 , 0 ) ) ; … } 需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。 首先,给对话基类增加一人成员变量CBursh : class CMyFormView : public CFormView { … private : CBrush m_ brush ; // background brush … } ; 其次, 在类的构造函数中将刷子初始化为所需要的背景颜色。 CMyFormView : : CMyFormView ( ) { // Initialize background brush . m_brush .CreateSolidBrush (RGB ( 0, 0, 255 ) ) } 最后,使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测nCtlColor参量。 HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor ) { // Determine if drawing a dialog box . If we are , return +handle to //our own background brush . Otherwise let windows handle it . if (nCtlColor = = CTLCOLOR _ DLG ) return (HBRUSH) m_brush .GetSafeHandle ( ) ; return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor ); } |
2006-10-8 15:55:47 | |
huzunbo
|
41.如何禁止对话框关闭按钮和浮动工具条上的系统菜单 1、禁止对话框中的关闭按钮有二种方法。 第一种方法,用ModiftMenu()涵数来实现: CMenu* pMenu = this->GetSystemMenu(FALSE); pMenu->ModifyMenu(SC_CLOSE,MF_BYCOMMAND | MF_GRAYED ); 第二种方法,用EnableMenuItem()涵数来实现: CMenu* pMenu = this->GetSystemMenu(FALSE); pMenu->EnableMenuItem( SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); 2、禁止浮动工具条上的系统菜单。 新建一个CToolBar的派生类CxxToolBar,在新类中的左键双击(CxxToolBar::OnLButtonDblClk(...)) 和左键单击(CxxToolBar:: OnLButtonDown(...))涵数中分别加入下面代码既可: if (IsFloating()) //工具条正在浮动状态中 { CWnd* pMiniFrame; CWnd* pDockBar; pDockBar = GetParent(); pMiniFrame = pDockBar->GetParent(); //去除其上系统菜单 pMiniFrame->ModifyStyle(WS_SYSMENU, NULL); //重绘工具条 pMiniFrame->ShowWindow(SW_HIDE); pMiniFrame->ShowWindow(SW_SHOW); } 3、禁止窗口最大化按钮 在PreCreateWindow()涵数中去掉WS_MAXIMIZEBOX风格显示既可。 BOOL CxxFrameWnd::PreCreateWindow(CREATESTRUCT& cs) { cs.style &= ~WS_MAXIMIZEBOX; return CFrameWnd::PreCreateWindow(cs); } 42.如何拷贝一个工程的对话框资源到另一个工程中? 有两种方法可以实现: 1)你可以直接拷贝resource,用VC++以文本的方式或者直接用文本编辑器打开.rc文件,将有关的片段从 一个工程拷贝到另一个工程.你可以通过查找如下字样的片段(此片段用来定义对话框资源)来拷贝你要 的部分: IDD_MYDIALOG_ID DIALOG DISCARDABLE 0, 0, 235, 55 这里的IDD_MYDIALOG_ID是你的对话框的ID,将到此片段结尾的部分全拷下来,通常你还要给新的工程 加一个ID(通过DevStudio的工具或者直接修改resource.h文件). 2)可以通过DevStudio的copy/paste功能.首先,在编辑器以"auto"模式打开.rc文件,这时resource 正确的显示出来.然后,选中要拷贝的对话框的ID,在Edit菜单里选Copy或者按住Ctrl+C.然后打开目标 resource文件,在Edit菜单里选Paste或者按住Ctrl+V. 43.如何实现点一下对话框外面的区域,自动隐藏对话框? [问题提出] 如果想在点击对话框外面的地方使得对话框关闭,该如何做? [解决方法] 试试下面的代码,原理是在激活对话框时,捕获鼠标的动作,当鼠标点击时判断是否点击在对话框外,是的话就释放对话框. [程序实现] 建立名为My的对话框程序.实现如下步骤: 在MyDlg.h中加入: class CShowWindow1Dlg : public CDialog { // Construction public: int m_cx; int m_cy; ...... }; 在MyDlg.cpp中: //定义消息映象,处理鼠标单击及激活 BEGIN_MESSAGE_MAP(CMyDlg, CDialog) //{{AFX_MSG_MAP(CMyDlg) ON_WM_LBUTTONDOWN() ON_WM_ACTIVATE() //}}AFX_MSG_MAP END_MESSAGE_MAP() void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point) { CRect rect; GetClientRect(&rect); rect.InflateRect(m_cx, m_cy); //Release dialog if the user click outside it. if(!rect.PtInRect(point)) { EndDialog(IDCANCEL); } CDialog::OnLButtonDown(nFlags, point); } void CMyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) { CDialog::OnActivate(nState, pWndOther, bMinimized); if( nState == WA_ACTIVE || nState == WA_CLICKACTIVE) SetCapture(); else ReleaseCapture(); } BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); ..... OSVERSIONINFO info; memset((char*)&info, 0, sizeof(OSVERSIONINFO)); info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if(GetVersionEx(&info)) { //we don't run on Win32s, so check only two values if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { //On windows 95 m_cx = GetSystemMetrics(SM_CXFIXEDFRAME); m_cy = GetSystemMetrics(SM_CYFIXEDFRAME); } else { //On NT m_cx = GetSystemMetrics(SM_CXDLGFRAME); m_cy = GetSystemMetrics(SM_CYDLGFRAME); } } } 说明: 1)WM_ACTIVATE消息在ClassWizard中没有,按如下步骤添加,右击CMyDlg类,选Add Windows Message Handle,接着在Filter for messages available to中选Window,在New Windows messages/events列表中就会出现WM_ACTIVATE,选中,点击Add Handler 2)SM_CXDLGFRAME,SM_CYDLGFRAME NT中取得有WS_DLGFRAMEstyle风格的窗口的高和宽 95中已经废弃而采用SM_CX_FIXEDFRAME和SM_CYFIXEDFRAME 44. 初始化应用程序的大小 如果想使应用程序界面(文档)在开始运行是按你的尺寸展现在屏幕上, 添加代码如下: BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { int xsize=::GetSystemMetrics(SM_CXSCREEN); int ysize=::GetSystemMetrics(SM_CYSCREEN); cs.cx=xsize*5/10; cs.cy=ysize*5/10; cs.x=(xsize-cs.cx)/2; cs.y=(ysize-cs.cy)/2; } 其中的5/10是你的初始界面占屏幕的百分比,可以自己修改。如果想使应用程序大小固定添加cs.style&=~WS_THICKFRAME; 45. 如何得到视图指针? [问题提出] 现在你有一个多线程的Demo,你想在多线程里处理视图指针里的函数,我们给这个函数起个名字:Put();该如何实现呢? //有两种方法可以实现你的要求: //1)第一种方法: //要是多线程不是在App.cpp里出现,那么要在多线程的.cpp中加上extern CYourApp theApp; //获得文档模板: POSITION curTemplatePos = theApp.GetFirstDocTemplatePosition(); CDocTemplate *m_doc=theApp.GetNextDocTemplate(curTemplatePos); //获得文档: curTemplatePos=m_doc->GetFirstDocPosition(); CYourDoc *m_pdoc=(CA8Doc*)m_doc->GetNextDoc(curTemplatePos); //获得视图: curTemplatePos=m_pdoc->GetFirstViewPosition(); CYourView *m_pview=(CYourView*)m_pdoc->GetNextView(curTemplatePos); //调用视图函数: m_pview->Put(); //2)第二种方法: //获得窗体指针: CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //获得与该窗体符合的视图: CYourView *m_pView = (CYourView *) pFrame->GetActiveView(); //调用视图函数: m_pView->Put(); 46. 如何使我的程序在启动时不创建一个新文档? [问题] 如何使我的程序在启动时不创建一个新文档? [解答] 在程序的InitInstance中的ProcessShellCommand函数之前加入: cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing 47. 如何将标题栏上的右键菜单屏蔽掉? [解决方法] 右键菜单是系统菜单,只要将其WS_SYSMENU的属性去掉即可. [程序实现] int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { ........ long style = GetWindowLong(m_hWnd, GWL_STYLE); style &= ~WS_SYSMENU; SetWindowLong(m_hWnd, GWL_STYLE, style); return 0; } 48.如何全屏显示(没有标题,没有菜单,没有工具条) [解决方法] 重载CMainFrame的ActivateFrame函数: void CMainFrame::ActivateFrame(int nCmdShow) { CRect cRectdesktop; WINDOWPLACEMENT windowplacement; ::GetWindowRect(::GetDesktopWindow(),&cRectdesktop); ::AdjustWindowRectEx(&cRectdesktop,GetStyle(),TRUE,GetExStyle()); windowplacement.rcNormalPosition=cRectdesktop; windowplacement.showCmd=SW_SHOWNORMAL; SetWindowPlacement(&windowplacement); CFrameWnd::ActivateFrame(nCmdShow); } 49.如何设置有背景颜色的文本 (1)[解决方法] 用到了CDC::SetBkMode(); [程序实现] void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); CRect rcView;//加這兩句 GetClientRect(rcView); // TODO: add draw code for native data here CString str (_T("Perfect Text...")); pDC->SetBkMode(TRANSPARENT); rcView.OffsetRect (1,1); pDC->SetTextColor(RGB (0,0,0)); pDC->DrawText(str,str.GetLength(),rcView,DT_SINGLELINE | DT_CENTER | DT_VCENTER); rcView.OffsetRect(-1,-1); pDC->SetTextColor(RGB (255,0,0)); pDC->DrawText(str,str.GetLength(),rcView,DT_SINGLELINE | DT_CENTER | DT_VCENTER); } (2) 建立名为My的SDI或MDI,并响应WM_ERASEBKGND. BOOL CMyView::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default CBrush Brush (RGB(114,147,171)); // Select the brush into the device context . CBrush* pOldBrush = pDC->SelectObject(&Brush); // Get the area that needs to be erased . CRect ViewClip; pDC->GetClipBox(&ViewClip); //Paint the area. pDC->PatBlt(ViewClip.left,ViewClip.top,ViewClip.Width(),ViewClip.Height(),PATCOPY); //Unselect brush out of device context . pDC->SelectObject (pOldBrush ); // Return nonzero to half fruther processing . return TRUE; return CView::OnEraseBkgnd(pDC); } 此方法也适合基类是EditView的SDI或MDI的情况,但是字体的颜色和底色不行.建议用WM_CTLCOLOR. 50.串太长时往让其末尾显示一个省略号(在SDI或MDI的View中) [问题提出] 如何在串太长时往让其末尾显示一个省略号(在SDI或MDI的View中)? [程序实现] 建立名为My的SDI或MDI工程. void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here pDC->DrawText(CString("It's a long string,so we will add a '...' at the end."),CRect (110, 110, 180, 130),DT_LEFT | DT_END_ELLIPSIS); //Add ellpsis to middle of string if it does not fit pDC->DrawText(CString("It's a long string,so we will add a '...' at the end."),CRect (110, 140, 300, 160),DT_LEFT | DT_PATH_ELLIPSIS); } |
2006-10-8 15:56:20 | |
huzunbo
|
51. 如何获得其他程序的图标,并显示在View中 [问题提出] 有的时候,如:类资源管理器会遇到获得程序图标并显示的操作,如何实现呢? [解决方法] SDK函数SHGetFileInfo来获得有关文件的很多信息:如大小图标,属性,类型等. [程序实现] 建立名为My的SDI工程.在OnPaint()函数中加入: void CMyView::OnPaint() { CPaintDC dc(this); // device context for painting HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0); if (hIcon && hIcon!=(HICON)-1) dc.DrawIcon(10,10,hIcon); // TODO: Add your message handler code here // Do not call CView::OnPaint() for painting messages } 说明:_T("NotePad.exe")指的是要获得什么程序的图标. 或者在OnDraw()中(此时必须保证没有OnPaint()函数,想想为何?) void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0); if (hIcon &&hIcon!=(HICON)-1) pDC->DrawIcon(10,10,hIcon); } 52 .RichEdit 在Dialog(FormView中打开)中加入CRichEdit控件后,这个dialog 为什么打不开如何处理? [解决方法] 在函数:InitInstance的第一句加入AfxInitRichEdit(); 53. 如何使FormView中显示dialog时,不是凹的? [问题提出] 为什么FormView中显示dialog时,是凹的,能不能不这样 [解决方法] 在Dialog的属性中: 增加属性WS_BORDER 或者 WS_EX_WINDOWEDGE 用程序实现: pView->ModifyStyle(,WS_BORDER) 或者pView->ModifyStyleEx(,WS_EX_WINDOWEDGE ) 54. 如何改变窗口标题? [问题提出] 在应用程序的不同运行时期,要反映当前状态往往会修改应用程序标题. [解决方法] 在MFC类库中提供了CWnd::SetWindowText函数,通过该函数可以改变任何窗体(包括控件)的标题. 改变主窗体的标题: CWnd *m_pMainWnd; m_pMainWnd=AfxGetMainWnd(); m_pMainWnd->SetWindowText(_T("改变标题")); 当改变多视MDI的子窗口的标题时,用: GetParentFrame()->SetWindowText(_T("MDI Child改变标题")); 当改变按钮的标题时(假设按钮的ID=IDC_BUTTON1): GetDlgItem(IDC_BUTTON1)->SetWindowText(_T("Button 改变标题")); 运行看看. 55.图标透明 (1).Windows中的图标其实是有两个图像组成的,其中一个用于与它要显示的位置的图像做“AND”操作,另一个作“XOR”操作。 透明:用“白色”AND,用“黑色”XOR 反色:用“白色”AND,用“白色”XOR 正常色:用“黑色”AND,用正常颜色XOR. (2). WIN9X中好像是对像素的操作实现透明的 WIN2K中就有API直接实现透明了! WIN2K中 GetWindowLong SetWindowLong SetLayeredWindowAttributes 三个API就可以实现透明了! (3) ::DrawIconEx(pDC->GetSafeHdc(),point.x,point.y,icon,icosize,icosize,0,NULL,DI_NORMAL); 56.ASSERT()是干什么用的 ASSERT()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。例如,变量n在程序中不应该为0,如果为0可能导致错误,你可以这样写程序: ...... ASSERT( n != 0); k = 10/ n; ...... ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。 assert()的功能类似,它是ANSI C标准中规定的函数,它与ASSERT的一个重要区别是可以用在Release版本中。 56. 将RADIO控件初始状态设置成为选中 1、"在OnInitialDialog中用CButton::CheckRadioButton(...) 2、"在OnInitialDialog中用CButton::SetCheck(...) 3、"关联一个整型值,在构造函数中设为0。 57.获得视图 CFrameWnd* pFrameWnd = (CFrameWnd*)theApp.GetMainWnd(); CMyView* pView = (CMyView*)pFrameWnd->GetActiveView(); 58.如何得到屏幕的真实尺寸 [问题提出] 我的屏幕是1024*800,如何得到屏幕的真实大小,我用GetSystemMetrics(SM_CYFULLSCREEN)得到的高度总是小于800 [问题解答] GetSystemMetrics(SM_CYFULLSCREEN)得到的只是屏幕用户区的大小。要得到屏幕的真实大小需要使用 GetDeviceCaps函数,该API函数原型是这样的: int GetDeviceCaps( HDC hdc, // handle to DC int nIndex // index of capability ); ///得到屏幕尺寸的代码如下 void CMyDlg::OnPaint() { CPaintDC dc(this); int cx = ::GetDeviceCaps(dc.m_hDC,HORZRES);///得到宽度 int cy = ::GetDeviceCaps(dc.m_hDC,VERTRES);///得到高度 CDialog::OnPaint(); 59. 修改标题栏高度 NONCLIENTMETRICS nm 调用SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(nm),&nm,0) 重设SystemParametersInfo(SPI_SETNONCLIENTMETRICS,sizeof(nm),&nm,0) 60. 如何实现“气球式”工具提示。 本程序介绍一个与CToolTipCtrl相似的类CTooolTipWnd。 使用该类的方法如下: 1. 增加ToolTipWnd.cpp到工程文件。 2. 在头文件中添加#include "ToolTipWnd.h" 。 3. 在类声明中添加: CToolTipWnd m_BalloonToolTip; 4. 在OnInitDialog(对话框)或OnInitialUpdate(表单视)中添加下面代码: m_BalloonToolTip.Create(this); m_BalloonToolTip.AddTool(GetDlgItem(), , [text color]); eg. m_BalloonToolTip.AddTool(GetDlgItem(IDC_EDIT1),"Tooltip", RGB(255,0,0)); 第三个参数为可选,缺省为RGB(0, 0, 0)。缺省文本颜色可以用SetDefTextColor进行设置。 4. 重载PreTranslateMessage并添加下面代码: if(m_BalloonToolTip) m_BalloonToolTip.RelayEvent(pMsg); |
2006-10-8 15:56:44 | |
huzunbo
|
61. dlg 上建立View的方法: OnInitDialog() { CDialog:;OnInitDialog(); CRect rectWindows; GetWinodwRect(&rectWindows); CRuntimeClass *pViewClass=RUNTIME_CLASS(CXXXView); CCreateContext *pContext=new CCreateContext; pContext->m_pCurrentDoc=NULL; pContext->m_pCurrentFrame=NULL; pContext->m_pLastView=NULL; pContext->m_pNewDocTemplate=NULL; pContext->m_pNewViewClass=pViewClass; CWnd *pWnd=DYNAMIC_DOWNCAST(CWnd,pviewClass->CreateObject()); pWnd->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0),this,pContext); delete pContext; CXXXView *pView=DYUNAMIC_DOWNCAST(CXXXView,pWnd); ............... } 62. 窗口最大化、最小化及关闭的消息是什么?如何截获? 最大化、最小化将发送WM_SYSCOMMAND消息。要处理该消息,可以这么做: 1、在Form的头文件中添加: void __fastcall RestrictMinimizeMaximize(TMessage &Msg); BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_SYSCOMMAND, TMessage, RestrictMinimizeMaximize) END_MESSAGE_MAP(TForm) 2、在Form的单元文件中添加: void __fastcall TForm1::RestrictMinimizeMaximize(TMessage& Msg) { if (Msg.WParam == SC_MINIMIZE) { //catches minimize... } else if (Msg.WParam == SC_MAXIMIZE) { //catches maximize... } TForm::Dispatch(&Msg); // or "else TForm::Dispatch(&Msg)" to trap } 关闭窗口的消息为WM_CLOSE,C++Builder提供了OnClose事件。 63. 如何遍历整个目录树查找文件 在应用程序的开发过程中,会遇到如何查找某一文件以确定此文件路径的问题。利用CFileFind类可以比较方便地在当前目录下进行文件查找,但却不能对其子目录中的文件进行搜寻。而实际应用中往往需要对某一整个目录树,甚至是整个C盘或D盘驱动器进行文件搜寻。通过实践,我们在Visual C++ 6.0中编程实现了如何遍历任意目录树,以查找某一特定的文件。 在下面的具体陈述中可以看到,在确定要查找的文件名和要进行搜索的目录的名称后,将调用函数Search_Directory进行文件的查找。首先依次查找当前目录下的每一个实体(文件或是子目录),如果是某一子目录,则进入该子目录并递归调用函数Search_Dirctory进行查找,查找完毕之后, 再返回上一级目录;如果不是子目录而是某一文件,则判断其是否就是我们要查找的文件,如果是则输出其完整的文件路径。这样,通过Search_Directory函数的反复递归调用,就可以实现对整个目录,包括子目录的遍历搜索。下面将举例详细讲述如何在VC++中编程实现在整个目录树中的文件查找。 1. 在Visual C++ 6.0(VC++ 5.0与之类似)中用默认方式创建了一基于对话框的应用程序Search。在主窗口对话框上放置一命令按钮,其Caption为“Search File”,ID为ID_BUTTON_SEARCH。单击此按钮将完成文件的查找工作。 2. 利用ClassWizard为“Search File”按钮的BN_CLICKED 事件添加处理函数OnButtonSearch,代码如下: #include 〈direct.h〉 #include 〈io.h〉 void CSearchDlg::OnButtonSearch() { // TODO: Add your control notification handler code here char szFilename[80]; // 字符串 szFilename 表示要查找的文件名 strcpy(szFilename,"Mytext.txt"); _chdir("d:\\"); // 进入要查找的路径(也可为某一具体的目录) // 查找文件, 如果查到则显示文件的路径全名 Search_Directory(szFilename); // 为CSearchDlg类的一成员函数 MessageBox(″查找文件完毕!″); // 显示查找完毕的信息 } 3. 在CSearchDlg类中增加成员函数Search_Directory,它将完成具体的文件查找工作,代码如下: void CSearchDlg::Search_Directory(char* szFilename) { long handle; struct _finddata_t filestruct; //表示文件(或目录)的信息 char path_search[_MAX_PATH]; //表示查找到的路径结果 // 开始查找工作, 找到当前目录下的第一个实体(文件或子目录), // "*"表示查找任何的文件或子目录, filestruct为查找结果 handle = _findfirst("*", &filestruct); // 如果handle为-1, 表示当前目录为空, 则结束查找而返回 if((handle == -1)) return; // 检查找到的第一个实体是否是一个目录(filestruct.name为其名称) if( ::GetFileAttributes(filestruct.name) & FILE_ATTRIBUTE_DIRECTORY ) { // 如果是目录, 则进入该目录并递归调用函数Search_Dirctory进行查找, // 注意: 如果目录名的首字符为'.'(即为"."或".."), 则不用进行查找 if( filestruct.name[0] != '.' ) { _chdir(filestruct.name); Search_Directory(szFilename); // 查找完毕之后, 返回上一级目录 _chdir(".."); } } else // 如果第一个实体不是目录, 则检查是否是要查找的文件 { // stricmp对两字符串进行小写形式的对比, 返回为0表示完全一致 if( !stricmp(filestruct.name, szFilename) ) { // 先获得当前工作目录的全路径 _getcwd(path_search,_MAX_PATH); // 再获得文件的完整的路径名(包含文件的名称) strcat(path_search,"\\"); strcat(path_search,filestruct.name); MessageBox(path_search); //输出显示 } } // 继续对当前目录中的下一个子目录或文件进行与上面同样的查找 while(!(_findnext(handle,&filestruct))) { if( ::GetFileAttributes(filestruct.name) & FILE_ATTRIBUTE_DIRECTORY ) { if(*filestruct.name != '.') { _chdir(filestruct.name); Search_Directory(szFilename); _chdir(".."); } } else { if(!stricmp(filestruct.name,szFilename)) { _getcwd(path_search,_MAX_PATH); strcat(path_search,"\\"); strcat(path_search,filestruct.name); MessageBox(path_search); } } } _findclose(handle); // 最后结束整个查找工作 } 这样我们就可以对整个目录进行遍历搜索,查找某一特定的文件,并输出显示其完整的文件路径。以上的程序在Visual C++ 6.0中已调试通过。 64. Richedit control的设置背景图片办法 1:继承CRichEditCtrl::OnEraseBkgnd(CDC* pDC)消息事件中,给Richedit控件绘制上背景图片:m_bmpBackground.DrawDIB(pDC, 0, 0, rc.Width(), rc.Height());当然也可以通过subclass richedit window之后,在回调函数中处理WM_ERASEBKGND消息。 2:设置了Richedit控件的透明属性; 3:依照kenwhale所说的,Hook了GDI32.DLL中的ExtTextOut函数,将RichEdit的text-output options去除ETO_OPAQUE style 。综上所述,即可实现RichEdit控件的背景图片效果。 据此,我还实现了RichEdit控件背景绘制AVI动画效果。 65. MFC程序中如何创建多级目录 BOOL mkdirEx(const char* lpPath) { CString pathname = lpPath; if(pathname.Right(1) != "\") pathname += "\" ; int end = pathname.ReverseFind('\'); int pt = pathname.Find('\'); if (pathname[pt-1] == ':') pt = pathname.Find('\', pt+1); CString path; while(pt != -1 && pt<=end) { path = pathname.Left(pt+1); if(_access(path, 0) == -1) _mkdir(path); pt = pathname.Find('\', pt+1); } return true; } 66. 解决外部符号错误:_main,_WinMain@16,__beginthreadex 在创建MFC项目时, 不使用MFC AppWizard向导, 如果没有设置好项目参数, 就会在编译时产生很多连接错误, 如error LNK2001错误, 典型的错误提示有: libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16 msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16 nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex 下面介绍解决的方法: 1). Windows子系统设置错误, 提示: libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main Windows项目要使用Windows子系统, 而不是Console, 可以这样设置: [Project] --> [Settings] --> 选择"Link"属性页, 在Project Options中将/subsystem:console改成/subsystem:windows 2). Console子系统设置错误, 提示: LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16 控制台项目要使用Console子系统, 而不是Windows, 设置: [Project] --> [Settings] --> 选择"Link"属性页, 在Project Options中将/subsystem:windows改成/subsystem:console 3). 程序入口设置错误, 提示: msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16 通常, MFC项目的程序入口函数是WinMain, 如果编译项目的Unicode版本, 程序入口必须改为wWinMainCRTStartup, 所以需要重新设置程序入口: [Project] --> [Settings] --> 选择"C/C++"属性页, 在Category中选择Output, 再在Entry-point symbol中填入wWinMainCRTStartup, 即可 4). 线程运行时库设置错误, 提示: nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex 这是因为MFC要使用多线程时库, 需要更改设置: [Project] --> [Settings] --> 选择"C/C++"属性页, 在Category中选择Code Generation, 再在Use run-time library中选择Debug Multithreaded或者multithreaded 其中, Single-Threaded单线程静态链接库(release版本) Multithreaded多线程静态链接库(release版本) multithreaded DLL多线程动态链接库(release版本) Debug Single-Threaded单线程静态链接库(debug版本) Debug Multithreaded多线程静态链接库(debug版本) Debug Multithreaded DLL多线程动态链接库(debug版本) 单线程: 不需要多线程调用时, 多用在DOS环境下 多线程: 可以并发运行 静态库: 直接将库与程序Link, 可以脱离MFC库运行 动态库: 需要相应的DLL动态库, 程序才能运行 release版本: 正式发布时使用 debug版本: 调试阶段使用 67. 创建包含多个子目录的目录 void CreateAllDirectories(CString strDir) { //remove ending / if exists if(strDir.Right(1)=="\\") strDir=strDir.Left(strDir.GetLength()-1); // base case . . .if directory exists if(GetFileAttributes(strDir)!=-1) return; // recursive call, one less directory int nFound = strDir.ReverseFind('\\'); CreateAllDirectories(strDir.Left(nFound)); // actual work CreateDirectory(strDir,NULL); } 68. ReverseFind() #include <STDIO.H> #include <AFX.H> int main() { CString s; s.Format("abcdefghijk"); int nPos = s.ReverseFind('a'); printf("nPos is %d\n",nPos); return 0; } 其中,'a'对应的nPos是0,'h'对应的nPos是7,以此类推。但是:s.ReverseFind('a')和s.Find('a')的结果是一样的。 问题是:ReverseFind() 和 Find() 有什么区别呢: 对于ReverseFind(),查找顺序是从后往前,找到后的nPos是按前后顺序排列的。 而Find()是从前往后查的,找到后的nPos也是按前后顺序排列的。 69. MDI中如何只屏蔽掉子框架的右上角的关闭按钮 int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1) return -1; 。。。 CMenu* pSysMenu = GetSystemMenu(FALSE); pSysMenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND |MF_DISABLED|MF_GRAYED); return 0; } 70. 程序如何删除自己 ///////////////////////////////////////////////// int WINAPI WinMain(HINSTANCE h, HINSTANCE b, LPSTR psz, int n) { // Is this the Original EXE or the clone EXE? // If the command-line 1 argument, this is the Original EXE // If the command-line >1 argument, this is the clone EXE if (__argc == 1) { // Original EXE: Spawn clone EXE to delete this EXE // Copy this EXEcutable image into the user''s temp directory TCHAR szPathOrig[_MAX_PATH], szPathClone[_MAX_PATH]; GetModuleFileName(NULL, szPathOrig, _MAX_PATH); GetTempPath(_MAX_PATH, szPathClone); GetTempFileName(szPathClone, __TEXT("Del"), 0, szPathClone); CopyFile(szPathOrig, szPathClone, FALSE); //***注意了***: // Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL, OPEN_EXISTI NG, FILE_FLAG_DELETE_ON_CLOSE, NULL); // Spawn the clone EXE passing it our EXE''s process handle // and the full path name to the Original EXE file. TCHAR szCmdLine[512]; HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE, GetCurrentProcessId()); wsprintf(szCmdLine, __TEXT("%s %d \"%s\""), szPathClone, hProcessOrig, szPat hOrig); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); CloseHandle(hProcessOrig); CloseHandle(hfile); // This original process can now terminate. } else { // Clone EXE: When original EXE terminates, delete it HANDLE hProcessOrig = (HANDLE) _ttoi(__targv[1]); WaitForSingleObject(hProcessOrig, INFINITE); CloseHandle(hProcessOrig); DeleteFile(__targv[2]); // Insert code here to remove the subdirectory too (if desired). // The system will delete the clone EXE automatically // because it was opened with FILE_FLAG_DELETE_ON_CLOSE } return(0); } 这一段程序思路很简单:不是不能在运行时直接删除本身吗?好,那么程序先复制(CLONE)一个自己,用复制品起动另一个进程,然后自己结束运行,则原来的EXE文件不被系统保护.这时由新进程作为杀手删除原来的EXE文件,并且继续完成程序其他的功能。 新进程在运行结束后,复制品被自动删除。这又是值得介绍的一个把戏了,注意: // Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL,OPEN_EXISTIN G, FILE_FLAG_DELETE_ON_CLOSE, NULL); 这里面的FILE_FLAG_DELETE_ON_CLOSE标志,这个标志是告诉操作系统,当和这个文件相关的所有句柄都被关闭之后(包括上面这个CREATEFILE创建的句炳),就把这个文件删除。几乎所有的临时文件在创建时,都指明了这个标志。另外要注意的是:在复制品进程对原始程序操刀之前,应该等待原进程退出.在这里用的是进程同步技术.用HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE,GetCurrentProcessId());得到原进程句柄.SYNCHRONICE标志在NT下有效,作用是使OpenProcess得到的句柄可以做为同步对象.复制品进程用WaitForSingleObject函数进行同步,然后一个DeleteFile,以及进行其它销毁证据(比如删目录)的工作,一切就完事了。 程序是基于CONSOLE的,通过传入的参数确定是原始的进程还是复制品新进程,并且得到需要操作的目标文件的信息(主要是路径),复制品放在系统的TEMP目录(GetTempPath得到),你也可以随便找个你认为安全的地方(比如:WINDOWS\SYSTEM32等等)。这里面没有甚么深的技术.再看其他的一些实现删除自己的例子,比如说在进程退出前,用fwrite等方法输出一个.BAT文件,在里面写几句DEL,然后WINEXEC一下这个BAT文件即可.玩儿过DOS的虫虫大多都会。 |
2006-10-8 15:57:45 | |
huzunbo
|
71. 隐藏标题栏和菜单栏 隐藏标题栏 ModifyStyle(WS_CAPTION,0) 隐藏菜单栏 SetMenu(NULL) 72. InflateRect InflateRect这个函数用于增大或减小一个矩形的大小. 如m_graphRect.InflateRect(-70, -30, -30, -50); 将矩形左边坐标加70,上面加30,右边减30,下面减50。 73. 怎么让无模式对话框显示在主窗口后面 要解决这个问题的关键在于CDialog的Create并不能建立一个无属主的窗口.必须用另外方式建窗口. 比如你的对话框类叫CDlgNoOwner,在CMainFrame中加一个CDlgNoOwner类的成员变量, 弹出这个对话框的消息处理函数为 void CMainFrame::OnNoowner() { CDlgNoOwner *m_dlgTest=new CDlgNoOwner(this); HWND hwndDlg=::CreateDialog(AfxGetInstanceHandle(),MAKEINTRESOURCE(CDlgNoOwner::IDD),NULL/*owner*/,NULL/*dlgproc*/); //注意此处DLGPROC为NULL,并不要紧,因为接下要subclass啦 m_dlgTest->SubclassWindow (hwndDlg);//挂接到成员变量! m_dlgTest->ShowWindow (SW_SHOW); //这时可以看到一个"自由"的对话框弹出,和你的主窗口是平起平坐的. } 当然不要忘了在对话框关闭时DestroyWindow()..那都是在对话框类中的标准处理了. 74. 隐藏窗口(子窗口没有焦点时) 在程序启动时 InitDialog 中使用 SetWindowPos 将窗体设置到屏幕以外 然后再隐藏 1.在OnInitDialog()函数里设置定时器:(WINDOWS API里面响应消息WM_INITDIALOG) SetTimer(1, 1, NULL); 2.添加处理WM_TIMER的消息处理函数OnTimer,添加代码: if(nIDEvent == 1) { DeleteTimer(1); ShowWindow(SW_HIDE); } 75.修改视图背景 How do I change the background color of a view? To change the background color for a CView, CFrameWnd, or CWnd object, process the WM_ERASEBKGND message. The following code shows how: BOOL CSampleView::OnEraseBkgnd(CDC* pDC) { // Set brush to desired background color. CBrush backBrush(RGB(255, 128, 128)); // Save old brush. CBrush* pOldBrush = pDC->SelectObject(&backBrush); CRect rect; pDC->GetClipBox(&rect); // Erase the area needed. pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); pDC->SelectObject(pOldBrush); return TRUE; } I solved the problem like this: HBRUSH dlgtest::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { switch (nCtlColor) { case CTLCOLOR_BTN: case CTLCOLOR_STATIC: { pDC->SetBkMode(TRANSPARENT); } case CTLCOLOR_DLG: { CBrush* back_brush; COLORREF color; color = (COLORREF) GetSysColor(COLOR_BTNFACE); back_brush = new CBrush(color); return (HBRUSH) (back_brush->m_hObject); } } return(CFormView::OnCtlColor(pDC, pWnd, nCtlColor)); } 76. 如何实现点击对话框外的地方使对话框到主窗口的后面 只能将桌面做为父窗口 pMDlg = new CMDlg; pMDlg->Create(IDD_M_DIALOG,CWnd::GetDesktopWindow()/* 设置父窗口 */); pMDlg->ShowWindow(SW_SHOW); 然后在任务栏里隐藏对话框程序 如何让对话框应用程序在在任务栏上不出现,并且不隐藏窗口。 [解决方法] 把对话框的扩展属性修改成为WS_EX_TOOLWINDOW。 [程序实现] 把对话框的属性设置成为toolwindow,然后在需要的地方执行本代码。 DWORD Style = ::GetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE); Style = WS_EX_TOOLWINDOW ; AfxGetMainWnd()->ShowWindow(FALSE); ::SetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE,Style); AfxGetMainWnd()->ShowWindow(TRUE); |
用CTRL+W打开ClassWizard;
点击Class Info页,类名是工程名Dlg,
再在左下方的"Filter"中选择"Windows";
回到Message Maps页,就可以看到消息中有WM_WINDOWPOSCHANGING,
加入代码,如上所示.
这样运行*.EXE,不但看不到主界面,任务栏也没有,就是任务管理器中的"应用程序"中也不列出,那该如何关闭它?
在任务管理器的"进程"中可以找到它,这是黑客程序常用的方法.
如果需要的话,连"进程"中也看不到.这样要终止它就是问题了.
78.修改打印预览的ToolBar
为AFX_IDD_PREVIEW_TOOLBAR这个ID创建一个DialogBar。则系统就会用新创建的DialogBar代替系统默认的那个
79. 如何实现SDI与MDI的转换?
我想将一个编好的SDI应用程序转换为MDI,很明显要有多处的改变。
你可以这样做:建立一个继承于CMDIChidWnd的类,不防设为CChldFrm.在CWinApp中作如下变化。
InitInstance()
{
. ...
//instead of adding CSingleDocTemplate
// Add CMultiDocTemplate.
pDocTemplate = new CMultiDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CSDIDoc),
RUNTIME_CLASS(CChldFrm),
// For Main MDI Frame change this frame window from
// CFrameWnd derivative ( i.e. CMainFrame )
// to your CMDIChildWnd derived CChldFrm.
RUNTIME_CLASS(CSDIView));
/// After this it is required to create the main frame window
// which will contain all the child windows. Now this window is
// what was initially frame window for SDI.
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
.....
}
在从CMDIFrameWnd中继承的类CMainFrame代替CFramWnd后,所有的类都将从CMDIFrame继承,而不是CFrameWnd,编译运行后你就会发现程序已经从SDI变换到MDI。
注意:在CMainFram中必须将构造函数从private改为public.否则会出错。
80. CDC中的竖排文本?
在OnDraw成员函数中我想让文本竖直对齐,但CDC类似乎不支持该处理
方法一:如果你的竖直对齐是指旋转文本的话,下面的代码会对你有帮助:该代码检查一个Check box控制,查看文本是否需要旋转.
// m_pcfYTitle is a CFont* to the selected font.
// m_bTotateYTitle is a bool (==TRUE if rotated)
void CPage1::OnRotateytitle()
{
LOGFONT lgf;
m_pcfYTitle->GetLogFont(&lgf);
m_bRotateYTitle=
((CButton*)GetDlgItem(IDC_ROTATEYTITLE))->GetCheck()>0;
// escapement is reckoned clockwise in 1/10ths of a degree:
lgf.lfEscapement=-(m_bRotateYTitle*900);
m_pcfYTitle->DeleteObject();
m_pcfYTitle->CreateFontIndirect(&lgf);
DrawSampleChart();
}
注意如果你从CFontDialog中选择了不同的字体,你应该自己设定LOGFONT的lfEscapement成员.将初始化后的lfEscapement值传到CFontDialog中.
方法二:还有一段代码可参考:
LOGFONT LocalLogFont;
strcpy(LocalLogFont.lfFaceName, TypeFace);
LocalLogFont.lfWeight = fWeight;
LocalLogFont.lfEscapement = Orient;
LocalLogFont.lfOrientation = Orient;
if (MyFont.CreateFontIndirect(&LocalLogFont))
{
cMyOldFont = cdc->SelectObject(&MyFont);
}
81. 如何用键盘滚动分割的视口?
我的问题是当我用鼠标滚动分割窗口时,视口滚动都很正常,但用键盘时,却什么也没有发生.
在你的视图继承类中加入如下两个函数,假定该类为CScrollerView:
void CScrollerView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
BOOL processed;
for (unsigned int i=0;i< nRepCnt&&processed;i++)
processed=KeyScroll(nChar);
if (!processed)
CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}
BOOL CScrollerView::KeyScroll(UINT nChar)
{
switch (nChar)
{
case VK_UP:
OnVScroll(SB_LINEUP,0,NULL);
break;
case VK_DOWN:
OnVScroll(SB_LINEDOWN,0,NULL);
break;
case VK_LEFT:
OnHScroll(SB_LINELEFT,0,NULL);
break;
case VK_RIGHT:
OnHScroll(SB_LINERIGHT,0,NULL);
break;
case VK_HOME:
OnHScroll(SB_LEFT,0,NULL);
break;
case VK_END:
OnHScroll(SB_RIGHT,0,NULL);
break;
case VK_PRIOR:
OnVScroll(SB_PAGEUP,0,NULL);
break;
case VK_NEXT:
OnVScroll(SB_PAGEDOWN,0,NULL);
break;
default:
return FALSE; // not for us
// and let the default class
// process it.
}
return TRUE;
}
82. 如何改变默认的光标形状?
我试着将光标改变为其它的形状和颜色,但却没有变化.
在对话框/窗口/你需要的地方加上对WM_SETCURSOR消息的处理.
BOOL MyDialog::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// TOD Add your message handler code here and/or call default
::SetCursor(AfxGetApp()->LoadCursor(IDC_MYCURSOR));
return TRUE;
//return CDialog::OnSetCursor(pWnd, nHitTest, message);
}
你没有成功的原因是因为窗口类光标风格不能为NULL.
83. 如何选择CTreeCtrl中的节点文本进行编辑?
在向CTreeCtrl中加入一项后,有什么方法可以编辑该节点的文本呢?
首先设置你的CcompTreeCtrl具有TVS_EDITLABELS属性.在设计时用控件属性来设置在运行时用GetStyle()/SetStyle()成员函数来设置.然后请看下述代码:
HTREEITEM CCompTreeCtrl::AddSet()
{
static int setCnt =3D 1;
HTREEITEM hItem;
CString csSet;
//create text for new note: New Set 1, New Set 2 ...
csSet.Format( _T( "New Set %d" ), setCnt++ );
hItem =3D InsertItem( csSet, IMG_CLOSEDFOLDER, IMG_CLOSEDFOLDER );
if( hItem !=3D NULL )
EditLabel( hItem );
return hItem;
}
84. CListCtrl中选择变化时如何获得通知?
我在Report View中使用了一个CListCtrl(自绘制类型),我想知道什么时候选择项发生了改变.
在选择项变化时,可以使用按钮有效或失效,按如下操作:
加入LVN_ITEMCHANGED消息处理.
void CYourClassNameHere::OnItemchangedEventList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
*pResult = 0;
if (pNMListView->uChanged == LVIF_STATE)
{
if (pNMListView->uNewState)
GetDlgItem(IDC_DELETE)->EnableWindow(TRUE);
else
GetDlgItem(IDC_DELETE)->EnableWindow(FALSE);
}
}
85. List控件中整栏选择?
我在处理List控件时碰到了麻烦,我想创建一个ListView,来依据Tree控件的选择同时在ListView和ReportView中显示列表的信息.以下是相关的代码:
// Set full line select
ListView_SetExtendedListViewStyle(m_plstCustomers->GetSafeHwnd(),
LVS_EX_FULLROWSELECT);
按如下方法处理:
// -------------------- begin of snippet --------------------------------
bool CCommCtrlUtil32::ListCtrl_ModifyExtendedStyle(CListCtrl& p_rListCtrl,
const DWORD p_dwStyleEx,
const bool p_bAdd)
{
HWND t_hWnd = p_rListCtrl.GetSafeHwnd();
DWORD t_dwStyleEx = ListView_GetExtendedListViewStyle(t_hWnd);
if(p_bAdd)
{
if(0 == (p_dwStyleEx & t_dwStyleEx))
{
// add style
t_dwStyleEx |= p_dwStyleEx;
}
}
else
{
if(0 != (p_dwStyleEx & t_dwStyleEx))
{
// remove style
t_dwStyleEx &= ~p_dwStyleEx;
}
}
ListView_SetExtendedListViewStyle(t_hWnd, t_dwStyleEx);
return true;
}
86. 如何限制mdi子框架最大化时的大小?
用ptMaxTrackSize代替prMaxSize,如下所示:
void CChildFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
// TOD Add your message handler code here and/or call default
CChildFrame::OnGetMinMaxInfo(lpMMI);
lpMMI->ptMaxTrackSize.x = 300;
lpMMI->ptMaxTrackSize.y = 400;
}
87. 怎样实现3D效果?
在对话框中怎样实现Edit和Listboxes控件的3D效果?(环境95/NT VC5.0)
1). 使用带WS_EX_CLIENTEDGE标志的::CreateWindowEx来替换::CreateWindow 或者用CWnd::CreateEx替换CWnd::Create.
2).在建立控件之后,调用ModifyStyleEx(0, WS_EX_CLIENTEDGE).
88. How do I update the text of a pane in a status bar?
By default, a CStatusBar pane is not enabled when the pane is created. To activate a pane, you must call the ON_UPDATE_COMMAND_UI() macro for each pane on the status bar and update the panes. Because panes do not send WM_COMMAND messages, you cannot use ClassWizard to activate panes; you must type the code manually. For example, suppose one pane has ID_INDICATOR_PAGE as its identifier and that it contains the current page number in a document. To make the ID_INDICATOR_PAGE pane display text, add the following to a header file (probably the MAINFRM.H file):
afx_msg void OnUpdatePage(CCmdUI *pCmdUI);
Add the following to the application message map:
ON_UPDATE_COMMAND_UI(ID_INDICATOR_PAGE, OnUpdatePage)
Add the following to a source code file (probably MAINFRM.CPP):
void CMainFrame::OnUpdatePage(CCmdUI *pCmdUI)
{
pCmdUI->Enable();
}
To display text in the panes, either call SetPaneText() or call CCmdUI::SetText() in the OnUpdate() function. For example, you might want to set up an integer variable m_nPage that contains the current page number. Then, the OnUpdatePage() function might read as follows:
void CMainFrame::OnUpdatePage(CCmdUI *pCmdUI)
{
pCmdUI->Enable();
char szPage[16];
wsprintf((LPSTR)szPage, "Page %d", m_nPage);
pCmdUI->SetText((LPSTR)szPage);
}
This technique causes the page number to appear in the pane during idle processing in the same manner that the application updates other indicators.
89. 动态修改对话框的大小
[问题提出]
关于如何动态改变对话框的大小,我做了个Demo,大家看看.
[程序实现]
//本函数使用方法:
//第一个参数:如果是TRUE表示显示扩展的对话框,如果是FALSE,表示缩小对话框。
//第二个参数:表示本对话框的HWND,
//第三个参数:表示缩小后大小的控件的ID
void COptionDlg::ExpandBox(BOOL fExpand, HWND hwnd, int nIDDefaultBox)
{
CWnd *pWndBox=GetDlgItem(nIDDefaultBox);
RECT rcDefaultBox,rcChild,rcIntersection,rcWnd;
pWndBox->GetWindowRect(&rcDefaultBox);
HWND hwndChild = ::GetTopWindow(hwnd);
for (; hwndChild != NULL; hwndChild = ::GetNextWindow(hwndChild,GW_HWNDNEXT))
{
::GetWindowRect(hwndChild, &rcChild);
if (!IntersectRect(&rcIntersection, &rcChild, &rcDefaultBox))
::EnableWindow(hwndChild, fExpand);
}
::GetWindowRect(hwnd, &rcWnd);
if (GetWindowLong(hwnd, GWL_USERDATA) == 0)
{
SetWindowLong(hwnd, GWL_USERDATA,
MAKELONG(rcWnd.right - rcWnd.left,
rcWnd.bottom - rcWnd.top));
::ShowWindow(pWndBox->m_hWnd, SW_HIDE);
}
::SetWindowPos(hwnd, NULL, 0, 0,
rcDefaultBox.right - rcWnd.left,
rcDefaultBox.bottom - rcWnd.top,
SWP_NOZORDER | SWP_NOMOVE);
if(fExpand)
{
DWORD dwDims = GetWindowLong(hwnd, GWL_USERDATA);
::SetWindowPos(hwnd, NULL, 0, 0,
LOWORD(dwDims), HIWORD(dwDims), SWP_NOZORDER | SWP_NOMOVE);
::SendMessage(hwnd, DM_REPOSITION, 0, 0);
}
}
90. 用DoModal()调用模态对话框,总是显示在正中,我重载了它,并添加了MoveWindow(),可是其m_hWnd是一串零,调用失败。请问有何方法可使调用的模态对话框显示于自定义位置?多谢
我不清楚你把MoveWindow()加在什么地方了,正确的方法是在OnInitDialog中添加MoveWindow,如:
MoveWindow(0, 1, 300, 200);
需要注意的是前两个参数不能都为0。如果你确实希望把窗口放在(0, 0)处,可以在对话框设计窗口的属性中选中Absolute Align,然后再加入
MoveWindow(0, 0, 300, 200);
为什么会是这样?你看了MFC的源程序就会明白。原来MFC在调用你的OnInitDialog之后,会调用CDialog::CheckAutoCenter()(在dlgcore.cpp中)检查是否需要将窗口居中,你看了这个函数后就明白为什么需要上面那么做了。