亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

MFC程序設(shè)計(jì)常用技巧匯總

 更新時(shí)間:2015年05月25日 17:09:08   作者:惟愿蓮心不染塵  
這篇文章主要介紹了MFC程序設(shè)計(jì)常用技巧,實(shí)例匯總了MFC程序設(shè)計(jì)中常見(jiàn)的問(wèn)題與解決方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下

本文實(shí)例總結(jié)了MFC程序設(shè)計(jì)常用技巧。分享給大家供大家參考。具體如下:

1.屬性頁(yè)的添加:

創(chuàng)建對(duì)話框的類,該類要從CpropertyPage繼承;然后在要添加該對(duì)話框?yàn)閷傩皂?yè)的類(頭文件)里創(chuàng)建CpropertySheet類的一個(gè)對(duì)象m_tabsheet和新創(chuàng)建的對(duì)話框類的對(duì)象m_skatch;最后,在.cpp文件里的OnInitDialog()之類的函數(shù)里實(shí)現(xiàn)如下代碼:

復(fù)制代碼 代碼如下:
m_tabsheet.Create(this, WS_CHILD | WS_VISIBLE, 0);
//使選項(xiàng)卡的按鈕在下面
if(m_tabsheet.m_hWnd)
m_tabsheet.ShowWindow(SW_MAXIMIZE);//顯示選項(xiàng)卡
//加入標(biāo)簽,標(biāo)簽名由各個(gè)子對(duì)話框的標(biāo)題欄決定
m_tabsheet.AddPage(&m_skatch);
//用Create來(lái)創(chuàng)建一個(gè)屬性頁(yè)
m_tabsheet.Create(this, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT);
RECT rect;
m_tabsheet.GetWindowRect(&rect);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
//調(diào)整屬性頁(yè)的大小和位置
m_tabsheet.SetWindowPos(NULL, 225, 225, width-82, height,SWP_NOACTIVATE);

屬性頁(yè)的添加完成。如果要添加多個(gè)屬性頁(yè),則只需要增加多個(gè)對(duì)象,如下:
復(fù)制代碼 代碼如下:
m_tabsheet.AddPage(&m_skatch1);
m_tabsheet.AddPage(&m_skatch2);
. . . . . .

2.List Control中標(biāo)題欄(Column)的添加:

創(chuàng)建一個(gè)List Control,其ID為IDC_LIST,在其Styles屬性項(xiàng)下的View項(xiàng)里選擇Report、Align項(xiàng)里選擇Top、Sort項(xiàng)里選擇None.

然后在該List所在對(duì)話框的類(頭文件)里創(chuàng)建ClistCtrl的一個(gè)對(duì)象m_list然后在.cpp文件的OnInitDialog()之類的函數(shù)里實(shí)現(xiàn)如下代碼:

復(fù)制代碼 代碼如下:
CString strname[3];
strname[0]="Screen Name";
strname[1]="Form ID";
strname[2]="Category Path";
for(int i=0;i<3;i++)
{
m_List.InsertColumn(i,strname[i],LVCFMT_LEFT,130);
}

在這之前也要將List Control的ID與ClistCtrl的對(duì)象m_list在DoDataExchange(CDataExchange* pDX)函數(shù)里綁定,如下:

DDX_Control(pDX, IDC_LIST, m_List);

3.ToolBar和StatusBar中控件的添加:

方法⑴.只能在ToolBar里創(chuàng)建控件:首先,在ToolBar中創(chuàng)建一個(gè)Button,其ID為ID_TOOL_COMBO(我們要將創(chuàng)建的控件放在該Button的位置上).

其次,新創(chuàng)建一個(gè)類CMainToolBar,要從CToolBar繼承(創(chuàng)建過(guò)程大概如下:選擇工程/增加到工程/新的類;也可以選擇工程的根,然后點(diǎn)擊右鍵,選擇新的類;或者CTL+W,選擇增加類/新的類 --- 然后在class type里選擇Generic Class,在Name欄里輸入新類的名字,Base class里輸入CToolBar),創(chuàng)建成功后在該類里創(chuàng)建要增加的控件的對(duì)象,如:

復(fù)制代碼 代碼如下:
CComboBox m_wndMyCombo;
CStatic m_wndCategory, m_wndCategoryPath;
CButton m_wndOpenButton;
Cedit m_wndEdit;

然后在構(gòu)造函數(shù)里初始化如:
復(fù)制代碼 代碼如下:
m_wndMyCombo.m_hWnd = NULL;
m_wndCategory.m_hWnd = NULL;
m_wndCategoryPath.m_hWnd = NULL;
m_wndOpenButton.m_hWnd = NULL;
m_wndEdit.m_hWnd = NULL;

接著在CMainframe的頭文件里創(chuàng)建CMainToolBar的一個(gè)對(duì)象m_wndToolBar,最后在.cpp文件的OnCreate函數(shù)的最后實(shí)現(xiàn)如下:
復(fù)制代碼 代碼如下:
int index = 0;
CRect rect;  // 可定義在頭文件當(dāng)中
// ComboBox
{
//找到指定的工具項(xiàng)
while(m_wndToolBar.GetItemID(index)!=ID_TOOL_COMBO)
index++;
//設(shè)置指定工具項(xiàng)的寬度并獲取新的區(qū)域 120是寬度
m_wndToolBar.SetButtonInfo(index, ID_TOOL_COMBO, TBBS_SEPARATOR, 120);
m_wndToolBar.GetItemRect(index, &rect);
//設(shè)置位置
rect.top+=1;
rect.bottom += 200;
// 創(chuàng)建并顯示控件
if(!m_wndToolBar.m_wndMyCombo.Create(WS_CHILD|WS_VISIBLE| CBS_AUTOHSCROLL|
CBS_DROPDOWNLIST | CBS_HASSTRINGS , rect, &m_wndToolBar, ID_TOOL_COMBO))
{ 
TRACE0("Failed to create combo-box\n");
return FALSE;
}
m_wndToolBar.m_wndMyCombo.ShowWindow(SW_SHOW);
//填充內(nèi)容
m_wndToolBar.m_wndMyCombo.AddString("25%");
m_wndToolBar.m_wndMyCombo.AddString("50%");
m_wndToolBar.m_wndMyCombo.AddString("75%");
//選擇默認(rèn)項(xiàng)
m_wndToolBar.m_wndMyCombo.SetCurSel(0);
//獲取到內(nèi)容并MSGBOX顯示出來(lái)
CString strContent;
m_wndToolBar.m_wndMyCombo.GetWindowText(strContent);
index = 0;
}

其他控件都類似創(chuàng)建(只需要注意一下各自的Create函數(shù)的參數(shù)即可)。

方法⑵.這種方法創(chuàng)建不太容易控制:直接在CMainframe的頭文件中創(chuàng)建要增加的控件的對(duì)象,如CButton的對(duì)象m_wndAboutButton,然后創(chuàng)建CToolBar或者CstatusBar的對(duì)象,如:CstatusBar的對(duì)象_wndStatusBar;再增加幾個(gè)函數(shù)如下:

Protected:
virtual void RecalcLayout(BOOL bNotify = TRUE);
afx_msg void CMainFrame::OnViewStatusBar();
接著在.cpp文件中將StatusBar的ID和OnViewStatusBar 函數(shù)綁定在一起,如下所示:

復(fù)制代碼 代碼如下:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  // {{AFX_MSG_MAP(CMainFrame)
  ON_COMMAND(ID_VIEW_STATUS_BAR, OnViewStatusBar)
  ON_WM_CREATE()
  // }}AFX_MSG_MAP
END_MESSAGE_MAP()

然后Create函數(shù)的最后(返回值之前)實(shí)現(xiàn)如下代碼:

復(fù)制代碼 代碼如下:
CRect rc;
VERIFY(m_wndAboutButton.Create(_T("MyAbout"),
  WS_VISIBLE,rc,this,ID_APP_ABOUT));
// TODO: Remove this if you don't want tool tips or a resizeable toolbar
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

再在RecalcLayout函數(shù)里實(shí)現(xiàn):

復(fù)制代碼 代碼如下:
CRect rc;
if (m_wndStatusBar.m_hWnd)
{
m_wndStatusBar.GetWindowRect(&rc);
ScreenToClient(&rc);
rc.right -= 50;
m_wndStatusBar.SetWindowPos(NULL,rc.left,rc.top,rc.Width(),rc.Height(),
SWP_NOZORDER);
rc.left = rc.right;
rc.right += 50;
m_wndAboutButton.SetWindowPos(NULL,rc.left,rc.top,rc.Width(),rc.Height(),
SWP_NOZORDER);
}

最后在OnViewStatusBar()里實(shí)現(xiàn):
復(fù)制代碼 代碼如下:
BOOL bShow = m_wndStatusBar.GetStyle() & WS_VISIBLE;
m_wndAboutButton.SetWindowPos(NULL, 0, 0, 0, 0,
SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|
(bShow ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));

ToolBar中的創(chuàng)建與此相同,只需更改一下句柄即可。

4.通過(guò)Control創(chuàng)建的控件,對(duì)其屬性的動(dòng)態(tài)控制:

在對(duì)話框類的頭文件里創(chuàng)建所要改變屬性的控件的對(duì)象,如要改變一個(gè)Button(其ID為IDC_MyButton)的屬性,則需創(chuàng)建Cbutton的對(duì)象m_button。然后在.cpp中的DoDataExchange函數(shù)里將Button的ID和創(chuàng)建的對(duì)象綁定在一起:

復(fù)制代碼 代碼如下:
//{{AFX_DATA_MAP(CPrintDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
DDX_Control(pDX, IDC_MyButton, m_button);
//}}AFX_DATA_MAP

然后可以在該函數(shù)的最后進(jìn)行初始化:
復(fù)制代碼 代碼如下:
m_button.EnableWindow(FALSE);

到這里已經(jīng)實(shí)現(xiàn)了改變屬性。如果要?jiǎng)討B(tài)改變其屬性,可如下實(shí)現(xiàn)(通過(guò)兩個(gè)Button的點(diǎn)擊改變起屬性):
復(fù)制代碼 代碼如下:
// RadioAll Button的點(diǎn)擊響應(yīng)函數(shù)
void CPrintDlg::OnRadioAll()
{
// TODO: Add your control notification handler code here
m_button.EnableWindow(TRUE);
}
// RadioSelect Button的點(diǎn)擊響應(yīng)函數(shù)
void CPrintDlg::OnRadioSelect()
{
// TODO: Add your control notification handler code here
m_button.EnableWindow(FALSE);
}

也可以通過(guò)一個(gè)Check Button的點(diǎn)擊來(lái)改變,在其點(diǎn)擊響應(yīng)函數(shù)里實(shí)現(xiàn):
復(fù)制代碼 代碼如下:
m_button.EnableWindow(!m_button.IsWindowEnabled());

其余控件屬性的改變都如此。

5.窗口的分割與??浚?br />                        
一、新建一個(gè)類CMySplitter,基類為CSplitterWnd

二、重載該類的OnMouseMove函數(shù):

復(fù)制代碼 代碼如下:
void CMySplitter::OnMouseMove(UINT nFlags, CPoint point)
{
// 限制切分條的運(yùn)動(dòng)范圍。
if(point.x<228||point.x>600)
{
CWnd::OnMouseMove(nFlags, point);
}
else
{
CSplitterWnd::OnMouseMove(nFlags, point);
}
}

三、 然后就可以跟一般的窗口分割那樣去做了,if(point.x<228||point.x>600)這里的范圍可以隨你去設(shè)置了 ^_^,夠簡(jiǎn)單吧。

四、切分窗口

在MaiFram.h建立切分條對(duì)象:

復(fù)制代碼 代碼如下:
protected:
CMySplitter m_wndSplitter; //切分窗口對(duì)象
//在MaiFram.cpp中實(shí)現(xiàn)窗口切分:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,CCreateContext* pContext)
{
// 創(chuàng)建拆分器窗口
if (!m_wndSplitter.CreateStatic(this, 1, 2))
return FALSE;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView),CSize(228,100), pContext) ||!m_wndSplitter.CreateView(0,1, RUNTIME_CLASS(CDataEditView), CSize(100, 100), pContext))
{
m_wndSplitter.DestroyWindow();
return FALSE;
}
return TRUE;
}

6.?、僭鯓釉诔绦蜷_(kāi)始的時(shí)候讓它最大化?
②vc++做出來(lái)的exe文件在窗體的右上方是沒(méi)有最大化和最小化按鈕的,怎樣實(shí)現(xiàn)這一功能?
③如何在顯示窗口時(shí),使最大化按鈕變灰?
①在App類里的C…App::InitInstance()中把m_pMainWnd->ShowWindow(SW_SHOW)改成m_pMainWnd->ShowWindow(SW_MAXIMIZE);
②在CreateWidnow時(shí)用WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX 風(fēng)格.
③ 第一種方法:

復(fù)制代碼 代碼如下:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
// disable the maxmini box
cs.style &= ~WS_MAXIMIZEBOX;
return TRUE;
}

第二種方法:
復(fù)制代碼 代碼如下:
CMenu *pMenu=AfxGetApp()->m_pMainWnd->GetSystemMenu(FALSE);
     int x=pMenu->GetMenuItemCount( );
     UINT pID=pMenu->GetMenuItemID(x-1);
     pMenu->EnableMenuItem(pID, MF_DISABLED);

第三種方法:
復(fù)制代碼 代碼如下:
ModifyStyle(WS_MAXIMIZEBOX, 0);

這個(gè)函數(shù)也可以是最大化按鈕失效!
并且可以在程序中動(dòng)態(tài)的改變窗口的風(fēng)格

7. 更改屬性頁(yè)標(biāo)題

復(fù)制代碼 代碼如下:
void CProSheet::SetPageTitle(int nPage, int nImage, CString strTitle)
{
 TC_ITEM item;
 //item.mask = TCIF_TEXT|TCIF_IMAGE;  //設(shè)置圖標(biāo)+文字
 item.mask = TCIF_IMAGE;    //只設(shè)置圖標(biāo)
 item.iImage = nImage;
// item.pszText = strTitle.GetBuffer(0);  //設(shè)置文字
 GetTabControl ()->SetItem (nPage, &item);
//要設(shè)置文字時(shí)就將上面2行有注釋符的代碼前的注釋符去掉
}

8. 創(chuàng)建動(dòng)態(tài)菜單
復(fù)制代碼 代碼如下:
void CMainFrame::OnSelectState(NMTOOLBAR* pnmtb, LRESULT *plr)
{
CMenu menu;
if(!menu.CreateMenu())
return;
menu.AppendMenu(MF_STRING,0,"開(kāi)始");
menu.AppendMenu(MF_STRING,0,"結(jié)束");
CRect rc;
m_wndToolBar.SendMessage(TB_GETRECT, pnmtb->iItem, (LPARAM)&rc); 
m_wndToolBar.ClientToScreen(&rc);
menu.TrackMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
rc.left, rc.bottom, this, &rc);
//menu.DestroyMenu();
menu.detach();
}

9.關(guān)于打印
1.要打印哪個(gè)視就
復(fù)制代碼 代碼如下:
((CMainFrame*)AfxGetMainWnd())->m_wndSplitter.SetActivePane(...)
//要打印的那個(gè)視對(duì)應(yīng)的Pane

2.有一個(gè)單文檔工程,文檔窗口被切分:左視圖由CTreeView 的派生類管理,右視圖由CListView 的派生類CMyListView(其為風(fēng)格為L(zhǎng)VS_REPORT)管理,我想為右視圖添加打印和打印預(yù)覽,我在MyListView.cpp中添加了
復(fù)制代碼 代碼如下:
ON_COMMAND(ID_FILE_PRINT,CListView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW,CListView::OnFilePrintPreview)還有
BOOL CMyListView::OnPreparePrinting(CPrintInfo* pInfo)
{
     // TODO: call DoPreparePrinting to invoke the Print dialog box
     // return CListView::OnPreparePrinting(pInfo);
     pInfo->SetMaxPage(2);
     BOOL bret=DoPreparePrinting(pInfo);
     pInfo->m_nNumPreviewPages=2;
     return bret;
}

3. 下面是從MSDN中摘出來(lái)的一段,是用來(lái)改變消息路由的。用了這段代碼之后,CView中的消息(菜單,控件,子窗口)將先被CMyShape類來(lái)處理。不知道你要的是不是這樣的效果。
復(fù)制代碼 代碼如下:
// This example illustrates extending the framework's standard command
// route from the view to objects managed by the view. This example
// is from an object-oriented drawing application, similar to the
// DRAWCLI sample application, which draws and edits "shapes".
BOOL CMyView::OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo)
{
      // Extend the framework's command route from the view to
      // the application-specific CMyShape that is currently selected
      // in the view. m_pActiveShape is NULL if no shape object
      // is currently selected in the view.
      if ((m_pActiveShape != NULL)
        && m_pActiveShape->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
       return TRUE;
      // If the object(s) in the extended command route don't handle
      // the command, then let the base class OnCmdMsg handle it.
      return CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
     }
     // The command handler for ID_SHAPE_COLOR (menu command to change
     // the color of the currently selected shape) was added to
     // the message map of CMyShape (note, not CMyView) using ClassWizard. 
     // The menu item will be automatically enabled or disabled, depending
     // on whether a CMyShape is currently selected in the view, that is,
     // depending on whether CMyView::m_pActiveView is NULL. It is not
     // necessary to implement an ON_UPDATE_COMMAND_UI handler to enable
     // or disable the menu item. 
(CMyShape, CCmdTarget)
 //{{AFX_MSG_MAP(CMyShape)
 ON_COMMAND(ID_SHAPE_COLOR, OnShapeColor)
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

如果你只是想調(diào)用OnFilePrint( )函數(shù),可以試一試下面的代碼,就和調(diào)用其它類中的函數(shù)一樣。
復(fù)制代碼 代碼如下:
CMDIFrameWnd *pFrame =
       (CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
// Get the active MDI child window.
CMDIChildWnd *pChild =
       (CMDIChildWnd *) pFrame->GetActiveFrame();
// or CMDIChildWnd *pChild = pFrame->MDIGetActive();
// Get the active view attached to the active MDI child
// window.
CMyView *pView = (CMyView *) pChild->GetActiveView();
pView->OnFilePrint( );

4.

復(fù)制代碼 代碼如下:
void CMyReportView::OnFileOpen()
{
char Filter[] = "Crystal Report files(*.rpt)|*.rpt|All files(*.*)|*.*||";
CRect rect;
CFileDialog OpenDlg(TRUE,0,0,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,(LPCTSTR)Filter,NULL);
if(OpenDlg.DoModal()!=IDOK) ///顯示文件對(duì)話框
return;
CString m_fName=OpenDlg.GetPathName(); ///取得文件名
if(m_CrystalReport)
m_CrystalReport.DestroyWindow();
GetClientRect(rect);
///////////////////創(chuàng)建控件///////////////
if (!m_CrystalReport.Create(AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),WS_CHILD|WS_VISIBLE,rect,this,IDC_CRYSTALREPORT1))
{
AfxMessageBox("控件創(chuàng)建失敗!");
return ;
}
m_CrystalReport.SetWindowParentHandle((long)(this->m_hWnd));///設(shè)置父窗口
m_CrystalReport.SetWindowBorderStyle(0); ///設(shè)置為沒(méi)有邊框
m_CrystalReport.SetWindowLeft(0); ///左空間
m_CrystalReport.SetWindowTop(0); ///頂部空間
m_CrystalReport.SetWindowControls(FALSE); ///不顯示工具條
m_CrystalReport.SetReportFileName(m_fName); ///設(shè)置報(bào)表文件
m_CrystalReport.SetWindowWidth(rect.Width()); ///設(shè)置窗口寬度
m_CrystalReport.SetWindowHeight(rect.Height()); ///設(shè)置窗口高度
m_CrystalReport.SetFormulas(0, "Company=\"VC知識(shí)庫(kù)\""); ///將報(bào)表中的Company變量的值設(shè)置為VC知識(shí)庫(kù)
m_CrystalReport.SetDestination(0); ///設(shè)置輸出對(duì)象是屏幕
m_CrystalReport.PrintReport(); ///顯示報(bào)表
}
void CMyReportView::OnFilePrint()
{
if(m_CrystalReport && m_CrystalReport.GetReportFileName() != "")
{
m_CrystalReport.SetDestination(1); ///設(shè)置輸出對(duì)象是打印機(jī)
m_CrystalReport.PrintReport(); ///打印
}

10. Scroll

創(chuàng)建一個(gè)基于CScrollview的SDI Project(在第6步中選CScrollview)
若你已創(chuàng)建了,這步可以省略。
然后:
改為如

復(fù)制代碼 代碼如下:
void CTestView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = 1024; //改這兩個(gè)
sizeTotal.cy = 768;  //
SetScrollSizes(MM_TEXT, sizeTotal);
}

11. 修改主窗口風(fēng)格

AppWizard生成的應(yīng)用程序框架的主窗口具有缺省的窗口風(fēng)格,比如在窗口標(biāo)題條中自動(dòng)添加文檔名、窗口是疊加型的、可改變窗口大小等。要修改窗口的缺省風(fēng)格,需要重載CWnd::PreCreateWindow(CREATESTRUCT& cs)函數(shù),并在其中修改CREATESTRUCT型參數(shù)cs。
CWnd::PreCreateWindow 函數(shù)先于窗口創(chuàng)建函數(shù)執(zhí)行。如果該函數(shù)被重載,則窗口創(chuàng)建函數(shù)將使用CWnd::PreCreateWindow 函數(shù)返回的CREATESTRUCT cs參數(shù)所定義的窗口風(fēng)格來(lái)創(chuàng)建窗口;否則使用預(yù)定義的窗口風(fēng)格。
CREATESTRUCT結(jié)構(gòu)定義了創(chuàng)建函數(shù)創(chuàng)建窗口所用的初始參數(shù),其定義如下:

復(fù)制代碼 代碼如下:
typedef struct tagCREATESTRUCT {
LPVOID lpCreateParams; // 創(chuàng)建窗口的基本參數(shù)
HANDLE hInstance; // 擁有將創(chuàng)建的窗口的模塊實(shí)例句柄
HMENU hMenu; // 新窗口的菜單句柄
HWND hwndParent; // 新窗口的父窗口句柄
int cy; // 新窗口的高度
int cx; // 新窗口的寬度
int y; // 新窗口的左上角Y坐標(biāo)
int x; // 新窗口的左上角X坐標(biāo)
LONG style; // 新窗口的風(fēng)格
LPCSTR lpszName; // 新窗口的名稱
LPCSTR lpszClass; // 新窗口的窗口類名
DWORD dwExStyle; // 新窗口的擴(kuò)展參數(shù)
} CREATESTRUCT;

CREATESTRUCT結(jié)構(gòu)的style域定義了窗口的風(fēng)格。比如,缺省的MDI主窗口的風(fēng)格中就包括FWS_ADDTOTITLE(在標(biāo)題條中顯示當(dāng)前的工作文檔名)、FWS_PREFIXTITLE(把文檔名放在程序標(biāo)題的前面)、WS_THICKFRAME(窗口具有可縮放的邊框)等風(fēng)格。由于多種風(fēng)格參數(shù)由邏輯或(“|”)組合在一起的,因此添加某種風(fēng)格,就只需用“|”把對(duì)應(yīng)的參數(shù)加到CREATESTRUCT結(jié)構(gòu)的style域中;刪除已有的風(fēng)格,則需用“&”連接CREATESTRUCT結(jié)構(gòu)的style域與該風(fēng)格的邏輯非值。

CREATESTRUCT結(jié)構(gòu)的x、y、cx、cy域分別定義了窗口的初始位置和大小,因此,在CWnd::PreCreateWindow 函數(shù)中給它們賦值,將能定義窗口的初始顯示位置和大小。

下例中的代碼將主框窗口的大小將固定為1/4屏幕,標(biāo)題條中僅顯示窗口名,不顯示文檔名。

復(fù)制代碼 代碼如下:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
// 修改主窗風(fēng)格
cs.style &= ~FWS_ADDTOTITLE; //去除標(biāo)題條中的文檔名
cs.style &= ~WS_THICKFRAME; //去除可改變大小的邊框
cs.style |= WS_DLGFRAME; //增加不能改變大小的邊框
// 確定主窗的大小和初始位置
int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);//獲得屏幕寬
int cyScreen = ::GetSystemMetrics(SM_CYSCREEN); //獲得屏幕高
cs.x = 0; // 主窗位于左上角
cs.y = 0;
cs.cx = cxScreen/2; // 主窗寬為1/2屏幕寬
cs.cy = cxScreen/2; // 主窗高為1/2屏幕高
return CMDIFrameWnd::PreCreateWindow(cs);
}

12. 控制滾動(dòng)條
復(fù)制代碼 代碼如下:
BOOL CDiagramShowView::PreTranslateMessage(MSG* pMsg)
{
CFileTreeDoc* pDoc = (CFileTreeDoc*)GetDocument();
CPoint point = GetScrollPosition();
if(pMsg->message == WM_KEYDOWN)
{
switch(pMsg->wParam)
{
case VK_LEFT:
if( point.x > 10)
{
EndPoint.x = EndPoint.x - 10;
EndPoint.y = EndPoint.y;
}
else
{
EndPoint.x = 0;
EndPoint.y = EndPoint.y;
}
ScrollToPosition(EndPoint);
InvalidateRect(NULL,TRUE);
break;
case VK_RIGHT:
if( point.x < pDoc->intDiagramColumnCount * pDoc->intColumnWidth - 10 )
{
EndPoint.x = EndPoint.x + 10;
EndPoint.y = EndPoint.y;
}
else
{
EndPoint.y = pDoc->intDiagramColumnCount * pDoc->intColumnWidth;
EndPoint.x = EndPoint.x;
}
ScrollToPosition(EndPoint);
InvalidateRect(NULL,TRUE);
break;
case VK_UP:
if( point.y > 10)
{
EndPoint.y = EndPoint.y - 10;
EndPoint.x = EndPoint.x;
}
else
{
EndPoint.y = 0;
EndPoint.x = EndPoint.x;
}
ScrollToPosition(EndPoint);
InvalidateRect(NULL,TRUE);
break;
case VK_DOWN:
if( point.y < pDoc->intDiagramRowCount * pDoc->intRowHeight - 10 )
{
EndPoint.y = EndPoint.y + 10;
EndPoint.x = EndPoint.x;
}
else
{
EndPoint.y = pDoc->intDiagramRowCount * pDoc->intRowHeight;
EndPoint.x = EndPoint.x;
}
ScrollToPosition(EndPoint);
InvalidateRect(NULL,TRUE);
break;
default:
break;
}
}
return FALSE;
}

// 通過(guò)正負(fù)號(hào)判斷是向上還是向下滾動(dòng)
if(zDelta==120) 
向上滾動(dòng)
if(zDelta==-120)
向下滾動(dòng)
BOOL CDiagramShowView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
CFileTreeDoc* pDoc = (CFileTreeDoc*)GetDocument();
CPoint point = GetScrollPosition();

if(zDelta==120)
{
if( point.y >= 20 )
{
EndPoint.x = point.x;
EndPoint.y = point.y;

EndPoint.x = EndPoint.x;
EndPoint.y = EndPoint.y - 20;
}
else
{
EndPoint.x = EndPoint.x;
EndPoint.y = 0;
}
}

if(zDelta==-120)
{
if( point.y <= pDoc->intDiagramRowCount * pDoc->intRowHeight - 20 )
{
EndPoint.x = point.x;
EndPoint.y = point.y;

EndPoint.x = EndPoint.x;
EndPoint.y = EndPoint.y + 20;
}
else
{
EndPoint.x = EndPoint.x;
EndPoint.y = EndPoint.y;
}
}

ScrollToPosition(EndPoint);
InvalidateRect(NULL,TRUE);
return CScrollView::OnMouseWheel(nFlags, zDelta, pt);
}


13. 屬性頁(yè)處理通知消息

CPropertyPageImpl有一個(gè)消息映射處理WM_NOTIFY。如果通知代碼是PSN_*的值,OnNotify()就會(huì)調(diào)用相應(yīng)的通知處理函數(shù)。這使用了編譯階段虛函數(shù)機(jī)制,從而使得派生類可以很容易的重載這些處理函數(shù)。
由于WTL 3和WTL 7設(shè)計(jì)的改變,從而存在兩套不同的通知處理機(jī)制。在WTL 3中通知處理函數(shù)返回的值與PSN_*消息的返回值不同,例如,WTL 3是這樣處理PSN_WIZFINISH的:

復(fù)制代碼 代碼如下:
case PSN_WIZFINISH:
lResult = !pT->OnWizardFinish();
break;

OnWizardFinish()期望返回TRUE結(jié)束向?qū)?,F(xiàn)ALSE阻止關(guān)閉向?qū)?。這個(gè)方法很簡(jiǎn)陋,但是IE5的通用控件對(duì)PSN_WIZFINISH處理的返回值添加了新解釋,他返回需要獲得焦點(diǎn)的窗口的句柄。WTL 3的程序?qū)⒉荒苁褂眠@個(gè)特性,因?yàn)樗鼘?duì)所有非0的返回值都做相同的處理。

在WTL 7中,OnNotify() 沒(méi)有改變 PSN_* 消息的返回值,處理函數(shù)返回任何文檔中規(guī)定的合法數(shù)值和正確的行為。當(dāng)然,為了向前兼容,WTL 3 仍然使用當(dāng)前默認(rèn)的工作方式,要使用WTL 7的消息處理方式,你必須在中including atldlgs.h一行之前添加一行定義:

復(fù)制代碼 代碼如下:
#define _WTL_NEW_PAGE_NOTIFY_HANDLERS

編寫(xiě)新的代碼沒(méi)有理由不使用WTL 7的消息處理函數(shù),所以這里就不介紹WTL 3的消息處理方式。

CPropertyPageImpl 為所有消息提供了默認(rèn)的通知消息處理函數(shù),你可以重載與你的程序有關(guān)的消息處理函數(shù)完成特殊的操作。默認(rèn)的消息處理函數(shù)和相應(yīng)的行為如下:

int OnSetActive() - 允許頁(yè)面成為激活狀態(tài)
BOOL OnKillActive() - 允許頁(yè)面成為非激活狀態(tài)
int OnApply() - 返回 PSNRET_NOERROR 表示應(yīng)用操作成功完成
void OnReset() - 無(wú)相應(yīng)的動(dòng)作
BOOL OnQueryCancel() - 允許取消操作
int OnWizardBack() - 返回到前一個(gè)頁(yè)面
int OnWizardNext() - 進(jìn)行到下一個(gè)頁(yè)面
INT_PTR OnWizardFinish() - 允許向?qū)ЫY(jié)束
void OnHelp() - 無(wú)相應(yīng)的動(dòng)作
BOOL OnGetObject(LPNMOBJECTNOTIFY lpObjectNotify) - 無(wú)相應(yīng)的動(dòng)作
int OnTranslateAccelerator(LPMSG lpMsg) - 返回 PSNRET_NOERROR 表示消息沒(méi)有被處理
HWND OnQueryInitialFocus(HWND hWndFocus) - 返回 NULL 表示將按Tab Order順序的第一個(gè)控件設(shè)為焦點(diǎn)狀態(tài)

14.使工具條上的按鈕點(diǎn)擊一次為按下,再點(diǎn)擊才彈起

復(fù)制代碼 代碼如下:
bCheck=m_RtfEditToolBar.GetToolBarCtrl().IsButtonChecked(ID_TB_BOLD);
m_RtfEditToolBar.GetToolBarCtrl().CheckButton(ID_TB_BOLD, !bCheck);

15. VC中基于 Windows 的精確定時(shí)
  
在工業(yè)生產(chǎn)控制系統(tǒng)中,有許多需要定時(shí)完成的操作,如定時(shí)顯示當(dāng)前時(shí)間,定時(shí)刷新屏幕上的進(jìn)度條,上位 機(jī)定時(shí)向下位機(jī)發(fā)送命令和傳送數(shù)據(jù)等。特別是在對(duì)控制性能要求較高的實(shí)時(shí)控制系統(tǒng)和數(shù)據(jù)采集系統(tǒng)中,就更需要精確定時(shí)操作。
眾所周知,Windows 是基于消息機(jī)制的系統(tǒng),任何事件的執(zhí)行都是通過(guò)發(fā)送和接收消息來(lái)完成的。 這樣就帶來(lái)了一些問(wèn)題,如一旦計(jì)算機(jī)的CPU被某個(gè)進(jìn)程占用,或系統(tǒng)資源緊張時(shí),發(fā)送到消息隊(duì)列 中的消息就暫時(shí)被掛起,得不到實(shí)時(shí)處理。因此,不能簡(jiǎn)單地通過(guò)Windows消息引發(fā)一個(gè)對(duì)定時(shí)要求 嚴(yán)格的事件。另外,由于在Windows中已經(jīng)封裝了計(jì)算機(jī)底層硬件的訪問(wèn),所以,要想通過(guò)直接利用 訪問(wèn)硬件來(lái)完成精確定時(shí),也比較困難。所以在實(shí)際應(yīng)用時(shí),應(yīng)針對(duì)具體定時(shí)精度的要求,采取相適 應(yīng)的定時(shí)方法。

VC中提供了很多關(guān)于時(shí)間操作的函數(shù),利用它們控制程序能夠精確地完成定時(shí)和計(jì)時(shí)操作。本文詳細(xì)介紹了 VC中基于Windows的精確定時(shí)的七種方式.

方式一:VC中的WM_TIMER消息映射能進(jìn)行簡(jiǎn)單的時(shí)間控制。首先調(diào)用函數(shù)SetTimer()設(shè)置定時(shí) 間隔,如SetTimer(0,200,NULL)即為設(shè)置200ms的時(shí)間間隔。然后在應(yīng)用程序中增加定時(shí)響應(yīng)函數(shù) OnTimer(),并在該函數(shù)中添加響應(yīng)的處理語(yǔ)句,用來(lái)完成到達(dá)定時(shí)時(shí)間的操作。這種定時(shí)方法非常 簡(jiǎn)單,可以實(shí)現(xiàn)一定的定時(shí)功能,但其定時(shí)功能如同Sleep()函數(shù)的延時(shí)功能一樣,精度非常低,最小 計(jì)時(shí)精度僅為30ms,CPU占用低,且定時(shí)器消息在多任務(wù)操作系統(tǒng)中的優(yōu)先級(jí)很低,不能得到及時(shí)響 應(yīng),往往不能滿足實(shí)時(shí)控制環(huán)境下的應(yīng)用。只可以用來(lái)實(shí)現(xiàn)諸如位圖的動(dòng)態(tài)顯示等對(duì)定時(shí)精度要求不高的情況。如示例工程中的Timer1。

方式二:VC中使用sleep()函數(shù)實(shí)現(xiàn)延時(shí),它的單位是ms,如延時(shí)2秒,用sleep(2000)。精度非常 低,最小計(jì)時(shí)精度僅為30ms,用sleep函數(shù)的不利處在于延時(shí)期間不能處理其他的消息,如果時(shí)間太 長(zhǎng),就好象死機(jī)一樣,CPU占用率非常高,只能用于要求不高的延時(shí)程序中。如示例工程中的Timer2。

方式三:利用COleDateTime類和COleDateTimeSpan類結(jié)合WINDOWS的消息處理過(guò)程來(lái)實(shí)現(xiàn)秒級(jí)延時(shí)。如示例工程中的Timer3和Timer3_1。以下是實(shí)現(xiàn)2秒的延時(shí)代碼:

復(fù)制代碼 代碼如下:
COleDateTime start_time = COleDateTime::GetCurrentTime();
COleDateTimeSpan end_time= COleDateTime::GetCurrentTime()-start_time;
while(end_time.GetTotalSeconds()< 2) //實(shí)現(xiàn)延時(shí)2秒
{
       MSG  msg;
       GetMessage(&msg,NULL,0,0);
       TranslateMessage(&msg);
       DispatchMessage(&msg);
       
       //以上四行是實(shí)現(xiàn)在延時(shí)或定時(shí)期間能處理其他的消息,
       //雖然這樣可以降低CPU的占有率,
       //但降低了延時(shí)或定時(shí)精度,實(shí)際應(yīng)用中可以去掉。
       end_time = COleDateTime::GetCurrentTime()-start_time;
}//這樣在延時(shí)的時(shí)候我們也能夠處理其他的消息。
   

方式四:在精度要求較高的情況下,VC中可以利用GetTickCount()函數(shù),該函數(shù)的返回值是 DWORD型,表示以ms為單位的計(jì)算機(jī)啟動(dòng)后經(jīng)歷的時(shí)間間隔。精度比WM_TIMER消息映射高,在較 短的定時(shí)中其計(jì)時(shí)誤差為15ms,在較長(zhǎng)的定時(shí)中其計(jì)時(shí)誤差較低,如果定時(shí)時(shí)間太長(zhǎng),就好象死機(jī)一樣,CPU占用率非常高,只能用于要求不高的延時(shí)程序中。如示例工程中的Timer4和Timer4_1。下列代碼可以實(shí)現(xiàn)50ms的精確定時(shí):

復(fù)制代碼 代碼如下:
DWORD dwStart = GetTickCount();
DWORD dwEnd  = dwStart;
do
{
     dwEnd = GetTickCount()-dwStart;
}while(dwEnd <50);

為使GetTickCount()函數(shù)在延時(shí)或定時(shí)期間能處理其他的消息,可以把代碼改為:
復(fù)制代碼 代碼如下:
DWORD dwStart = GetTickCount();
DWORD dwEnd  = dwStart;
do
{
       MSG  msg;
       GetMessage(&msg,NULL,0,0);
       TranslateMessage(&msg);
       DispatchMessage(&msg);
       dwEnd = GetTickCount()-dwStart;
}while(dwEnd <50);

雖然這樣可以降低CPU的占有率,并在延時(shí)或定時(shí)期間也能處理其他的消息,但降低了延時(shí)或定時(shí)精度。

方式五:與GetTickCount()函數(shù)類似的多媒體定時(shí)器函數(shù)DWORD timeGetTime(void),該函數(shù)定時(shí)精 度為ms級(jí),返回從Windows啟動(dòng)開(kāi)始經(jīng)過(guò)的毫秒數(shù)。微軟公司在其多媒體Windows中提供了精確定時(shí)器的底 層API持,利用多媒體定時(shí)器可以很精確地讀出系統(tǒng)的當(dāng)前時(shí)間,并且能在非常精確的時(shí)間間隔內(nèi)完成一 個(gè)事件、函數(shù)或過(guò)程的調(diào)用。不同之處在于調(diào)用DWORD timeGetTime(void) 函數(shù)之前必須將 Winmm.lib 和 Mmsystem.h 添加到工程中,否則在編譯時(shí)提示DWORD timeGetTime(void)函數(shù)未定義。由于使用該 函數(shù)是通過(guò)查詢的方式進(jìn)行定時(shí)控制的,所以,應(yīng)該建立定時(shí)循環(huán)來(lái)進(jìn)行定時(shí)事件的控制。如示例工程中的Timer5和Timer5_1。

方式六:使用多媒體定時(shí)器timeSetEvent()函數(shù),該函數(shù)定時(shí)精度為ms級(jí)。利用該函數(shù)可以實(shí)現(xiàn)周期性的函數(shù)調(diào)用。如示例工程中的Timer6和Timer6_1。函數(shù)的原型如下:

MMRESULT timeSetEvent( UINT uDelay,
                UINT uResolution,
                LPTIMECALLBACK lpTimeProc,
                WORD dwUser,
                UINT fuEvent )

該函數(shù)設(shè)置一個(gè)定時(shí)回調(diào)事件,此事件可以是一個(gè)一次性事件或周期性事件。事件一旦被激活,便調(diào)用指定的回調(diào)函數(shù), 成功后返回事件的標(biāo)識(shí)符代碼,否則返回NULL。函數(shù)的參數(shù)說(shuō)明如下:

uDelay:以毫秒指定事件的周期。
Uresolution:以毫秒指定延時(shí)的精度,數(shù)值越小定時(shí)器事件分辨率越高。缺省值為1ms。
LpTimeProc:指向一個(gè)回調(diào)函數(shù)。
DwUser:存放用戶提供的回調(diào)數(shù)據(jù)。
FuEvent:指定定時(shí)器事件類型:
TIME_ONESHOT:uDelay毫秒后只產(chǎn)生一次事件
TIME_PERIODIC :每隔uDelay毫秒周期性地產(chǎn)生事件。   

具體應(yīng)用時(shí),可以通過(guò)調(diào)用timeSetEvent()函數(shù),將需要周期性執(zhí)行的任務(wù)定義在LpTimeProc回調(diào)函數(shù) 中(如:定時(shí)采樣、控制等),從而完成所需處理的事件。需要注意的是,任務(wù)處理的時(shí)間不能大于周期間隔時(shí)間。另外,在定時(shí)器使用完畢后, 應(yīng)及時(shí)調(diào)用timeKillEvent()將之釋放。

方式七:對(duì)于精確度要求更高的定時(shí)操作,則應(yīng)該使用QueryPerformanceFrequency()和 QueryPerformanceCounter()函數(shù)。這兩個(gè)函數(shù)是VC提供的僅供Windows 95及其后續(xù)版本使用的精確時(shí)間函數(shù),并要求計(jì)算機(jī)從硬件上支持精確定時(shí)器。如示例工程中的Timer7、Timer7_1、Timer7_2、Timer7_3。
QueryPerformanceFrequency()函數(shù)和QueryPerformanceCounter()函數(shù)的原型如下:

復(fù)制代碼 代碼如下:
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
BOOL QueryPerformanceCounter(LARGE_INTEGER *lpCount);

數(shù)據(jù)類型ARGE_INTEGER既可以是一個(gè)8字節(jié)長(zhǎng)的整型數(shù),也可以是兩個(gè)4字節(jié)長(zhǎng)的整型數(shù)的聯(lián)合結(jié)構(gòu), 其具體用法根據(jù)編譯器是否支持64位而定。該類型的定義如下:

復(fù)制代碼 代碼如下:
typedef union _LARGE_INTEGER
{
      struct
      {
       DWORD LowPart ;// 4字節(jié)整型數(shù)
       LONG HighPart;// 4字節(jié)整型數(shù)
      };
      LONGLONG QuadPart ;// 8字節(jié)整型數(shù)
     
}LARGE_INTEGER ;

在進(jìn)行定時(shí)之前,先調(diào)用QueryPerformanceFrequency()函數(shù)獲得機(jī)器內(nèi)部定時(shí)器的時(shí)鐘頻率, 然后在需要嚴(yán)格定時(shí)的事件發(fā)生之前和發(fā)生之后分別調(diào)用QueryPerformanceCounter()函數(shù),利用兩次獲得的計(jì)數(shù)之差及時(shí)鐘頻率,計(jì)算出事件經(jīng) 歷的精確時(shí)間。下列代碼實(shí)現(xiàn)1ms的精確定時(shí):

復(fù)制代碼 代碼如下:
LARGE_INTEGER litmp;
LONGLONG QPart1,QPart2;
double dfMinus, dfFreq, dfTim;
QueryPerformanceFrequency(&litmp);
dfFreq = (double)litmp.QuadPart;// 獲得計(jì)數(shù)器的時(shí)鐘頻率
QueryPerformanceCounter(&litmp);
QPart1 = litmp.QuadPart;// 獲得初始值
do
{
     QueryPerformanceCounter(&litmp);
     QPart2 = litmp.QuadPart;//獲得中止值
     dfMinus = (double)(QPart2-QPart1);
     dfTim = dfMinus / dfFreq;// 獲得對(duì)應(yīng)的時(shí)間值,單位為秒
}while(dfTim<0.001);

其定時(shí)誤差不超過(guò)1微秒,精度與CPU等機(jī)器配置有關(guān)。 下面的程序用來(lái)測(cè)試函數(shù)Sleep(100)的精確持續(xù)時(shí)間:

復(fù)制代碼 代碼如下:
    LARGE_INTEGER litmp;
    LONGLONG QPart1,QPart2;
    double dfMinus, dfFreq, dfTim;
    QueryPerformanceFrequency(&litmp);
    dfFreq = (double)litmp.QuadPart;// 獲得計(jì)數(shù)器的時(shí)鐘頻率
    QueryPerformanceCounter(&litmp);
    QPart1 = litmp.QuadPart;// 獲得初始值
    Sleep(100);
    QueryPerformanceCounter(&litmp);
    QPart2 = litmp.QuadPart;//獲得中止值
    dfMinus = (double)(QPart2-QPart1);
    dfTim = dfMinus / dfFreq;// 獲得對(duì)應(yīng)的時(shí)間值,單位為秒  
  由于Sleep()函數(shù)自身的誤差,上述程序每次執(zhí)行的結(jié)果都會(huì)有微小誤差。下列代碼實(shí)現(xiàn)1微秒的精確定時(shí):
    LARGE_INTEGER litmp;
    LONGLONG QPart1,QPart2;
    double dfMinus, dfFreq, dfTim;
    QueryPerformanceFrequency(&litmp);
    dfFreq = (double)litmp.QuadPart;// 獲得計(jì)數(shù)器的時(shí)鐘頻率
    QueryPerformanceCounter(&litmp);
    QPart1 = litmp.QuadPart;// 獲得初始值
    do
    {
     QueryPerformanceCounter(&litmp);
     QPart2 = litmp.QuadPart;//獲得中止值
     dfMinus = (double)(QPart2-QPart1);
     dfTim = dfMinus / dfFreq;// 獲得對(duì)應(yīng)的時(shí)間值,單位為秒
    }while(dfTim<0.000001);

其定時(shí)誤差一般不超過(guò)0.5微秒,精度與CPU等機(jī)器配置有關(guān)。

16. 為對(duì)話框中的控件增加提示的簡(jiǎn)單方法

我學(xué)VC從VC知識(shí)庫(kù)中得到不少好處,相來(lái)都是一些熱心朋友們的幫助,在此表示感謝!本工程可分五步:

1、建一個(gè)基于對(duì)話框的程序TipTest,在CTipTestDlg中增加成員變量:

復(fù)制代碼 代碼如下:
CToolTipCtrl m_tip[2],CWnd *m_pSub[2];

2、在CTipTestDlg::OnInitDialog()函數(shù)中增加如下代碼:
復(fù)制代碼 代碼如下:
     pSub[0] = GetDlgItem(IDC_RADIO1);   //得到單選按鈕的指針
     pSub[1] = GetDlgItem(IDC_BUTTON1);
m_tip[0].Create(pSub[0],TTS_ALWAYSTIP); //創(chuàng)建CToolTipCtrl
m_tip[0].AddTool(pSub[0]);        //將CToolTipCtrl與相應(yīng)的控件對(duì)應(yīng)起來(lái)
m_tip[1].Create(pSub[1],TTS_ALWAYSTIP);
m_tip[1].AddTool(pSub[1]);
m_tip[0].SetTipTextColor(RGB(0,0,255)); //設(shè)定文字的顏色
m_tip[0].SetDelayTime(150);       //設(shè)定提示文字在控件上停留的時(shí)間

3、重載CTipTestDlg::PreTranslateMessage(MSG* pMsg)函數(shù),增加如下代碼:
復(fù)制代碼 代碼如下:
if(m_tip[0].m_hWnd!=NULL)
 m_tip[0].RelayEvent(pMsg); //如果m_tip[0]句柄不為空,就從主窗口中捕獲消息,如WM_MOUSEMOVE,WM_LBUTTONDOWN等消息
   if(m_tip[1].m_hWnd!=NULL)
     m_tip[1].RelayEvent(pMsg);

4、捕獲主窗口的WM_MOUSEMOVE消息,在CTipTestDlg::OnMouseMove(UINT nFlags, CPoint point)函數(shù)中增加如下代碼:
復(fù)制代碼 代碼如下:
m_tip[0].UpdateTipText("VC知識(shí)庫(kù)歡迎你!",pSub[0]);//鼠標(biāo)在相應(yīng)的控件上移動(dòng)時(shí)顯示提示文字
m_tip[1].UpdateTipText("http://vckbase.com",pSub[1]);

17.刪除文件夾
復(fù)制代碼 代碼如下:
// 刪除文件夾及其所有內(nèi)容
void CBaseDoc::RemoveFolder(const CString &strPathName)
{
  CString path = strPathName;
  if (path.Right(1) != _T("\\"))
    path += _T("\\");
  path += _T("*.*");
  CFileFind ff;
  BOOL res = ff.FindFile(path);
  while (res)
  {
    res = ff.FindNextFile();
    // 是文件時(shí)直接刪除
    if (!ff.IsDots() && !ff.IsDirectory())
      DeleteFile(ff.GetFilePath());
    else if (ff.IsDots())
      continue;
    else if (ff.IsDirectory())
    {
      path = ff.GetFilePath();
      // 是目錄時(shí)繼續(xù)遞歸,刪除該目錄下的文件
      RemoveFolder(path);
      ::RemoveDirectory(path);
    }
  }
}

18.消息映射

有對(duì)話框A,B
從A中發(fā)消息給B然后B處理。
準(zhǔn)備工作,先定義消息,如下

復(fù)制代碼 代碼如下:
#define WM_B_NOTIFY WM_USER + 300

首先,必須將B的對(duì)話框句柄傳送給A,暫時(shí)叫m_hWndB;
在A的發(fā)送消息的地方這樣寫(xiě):
復(fù)制代碼 代碼如下:
::SendMessage( m_hWndB,WM_B_NOTIFY,TRUE,NULL );

這樣A中的處理就完了,下面說(shuō)B 中的
首先定義消息處理函數(shù),如下
復(fù)制代碼 代碼如下:
void B::ModiNotify( WPARAM wParam, LPARAM lParam )
{
  MessageBox("小樣,我就不信,搞不定你!");
}

然后加消息隱射,如下:
復(fù)制代碼 代碼如下:
BEGIN_MESSAGE_MAP(CB, CDialog)
  //{{AFX_MSG_MAP(CRPServerDlg)
  ON_MESSAGE( WM_B_NOTIFY,ModiNotify )
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

19.給從CWnd派生的窗口添加滾動(dòng)條
復(fù)制代碼 代碼如下:
ModifyStyle(0,WS_VSCROLL);

20. SetWindowPos

函數(shù)功能:該函數(shù)改變一個(gè)子窗口,彈出式窗口式頂層窗口的尺寸,位置和Z序。子窗口,彈出式窗口,及頂層窗口根據(jù)它們?cè)谄聊簧铣霈F(xiàn)的順序排序、頂層窗口設(shè)置的級(jí)別最高,并且被設(shè)置為Z序的第一個(gè)窗口。 
  
     函數(shù)原型:BOOL  SetWindowPos(HWN  hWnd,HWND  hWndlnsertAfter,int  X,int  Y,int  cx,int  cy,UNIT.Flags); 
  
     參數(shù): 
  
     hWnd:窗口句柄。 
  
     hWndlnsertAfter:在z序中的位于被置位的窗口前的窗口句柄。該參數(shù)必須為一個(gè)窗口句柄,或下列值之一: 
  
     HWND_BOTTOM:將窗口置于Z序的底部。如果參數(shù)hWnd標(biāo)識(shí)了一個(gè)頂層窗口,則窗口失去頂級(jí)位置,并且被置在其他窗口的底部?!?
  
     HWND_DOTTOPMOST:將窗口置于所有非頂層窗口之上(即在所有頂層窗口之后)。如果窗口己經(jīng)是非頂層窗口則該標(biāo)志不起作用。 
  
     HWND_TOP:將窗口置于Z序的頂部。 
  
     HWND_TOPMOST:將窗口置于所有非頂層窗口之上。即使窗口未被激活窗口也將保持頂級(jí)位置。 
  
     查g看該參數(shù)的使用方法,請(qǐng)看說(shuō)明部分?!?
  
     x:以客戶坐標(biāo)指定窗口新位置的左邊界?!?
  
     Y:以客戶坐標(biāo)指定窗口新位置的頂邊界?!?
  
     cx:以像素指定窗口的新的寬度?!?
  
     cy:以像素指定窗口的新的高度?!?
  
     uFlags:窗口尺寸和定位的標(biāo)志。該參數(shù)可以是下列值的組合: 
  
     SWP_ASNCWINDOWPOS:如果調(diào)用進(jìn)程不擁有窗口,系統(tǒng)會(huì)向擁有窗口的線程發(fā)出需求。這就防止調(diào)用線程在其他線程處理需求的時(shí)候發(fā)生死鎖?!?
  
     SWP_DEFERERASE:防止產(chǎn)生WM_SYNCPAINT消息?!?
  
     SWP_DRAWFRAME:在窗口周圍畫(huà)一個(gè)邊框(定義在窗口類描述中)?!?
  
     SWP_FRAMECHANGED:給窗口發(fā)送WM_NCCALCSIZE消息,即使窗口尺寸沒(méi)有改變也會(huì)發(fā)送該消息。如果未指定這個(gè)標(biāo)志,只有在改變了窗口尺寸時(shí)才發(fā)送WM_NCCALCSIZE。 
  
     SWP_HIDEWINDOW;隱藏窗口?!?
  
     SWP_NOACTIVATE:不激活窗口。如果未設(shè)置標(biāo)志,則窗口被激活,并被設(shè)置到其他最高級(jí)窗口或非最高級(jí)組的頂部(根據(jù)參數(shù)hWndlnsertAfter設(shè)置)?!?
  
     SWP_NOCOPYBITS:清除客戶區(qū)的所有內(nèi)容。如果未設(shè)置該標(biāo)志,客戶區(qū)的有效內(nèi)容被保存并且在窗口尺寸更新和重定位后拷貝回客戶區(qū)?!?
  
     SWP_NOMOVE:維持當(dāng)前位置(忽略X和Y參數(shù))。 
  
  SWP_NOOWNERZORDER:不改變z序中的所有者窗口的位置。 
  
  SWP_NOREDRAW:不重畫(huà)改變的內(nèi)容。如果設(shè)置了這個(gè)標(biāo)志,則不發(fā)生任何重畫(huà)動(dòng)作。適用于客戶區(qū)和非客戶區(qū)(包括標(biāo)題欄和滾動(dòng)條)和任何由于窗回移動(dòng)而露出的父窗口的所有部分。如果設(shè)置了這個(gè)標(biāo)志,應(yīng)用程序必須明確地使窗口無(wú)效并區(qū)重畫(huà)窗口的任何部分和父窗口需要重畫(huà)的部分。 
  
  SWP_NOREPOSITION;與SWP_NOOWNERZORDER標(biāo)志相同?!?
  
  SWP_NOSENDCHANGING:防止窗口接收WM_WINDOWPOSCHANGING消息?!?
  
  SWP_NOSIZE:維持當(dāng)前尺寸(忽略cx和Cy參數(shù))。 
  
  SWP_NOZORDER:維持當(dāng)前Z序(忽略hWndlnsertAfter參數(shù))?!?
  
  SWP_SHOWWINDOW:顯示窗口。 
  
  返回值:如果函數(shù)成功,返回值為非零;如果函數(shù)失敗,返回值為零。若想獲得更多錯(cuò)誤消息,請(qǐng)調(diào)用GetLastError函數(shù)?!?
  
  備注:如果設(shè)置了SWP_SHOWWINDOW和SWP_HIDEWINDOW標(biāo)志,則窗口不能被移動(dòng)和改變大小。如果使用SetWindowLoog改變了窗口的某些數(shù)據(jù),則必須調(diào)用函數(shù)SetWindowPos來(lái)作真正的改變。使用下列的組合標(biāo)志:SWP_NOMOVEISWP_NOSIZEISWP_FRAMECHANGED?!?
  
  有兩種方法將窗口設(shè)為最頂層窗口:一種是將參數(shù)hWndlnsertAfter設(shè)置為HWND_TOPMOST并確保沒(méi)有設(shè)置SWP_NOZORDER標(biāo)志;另一種是設(shè)置窗口在Z序中的位置以使其在其他存在的窗口之上。當(dāng)一個(gè)窗口被置為最頂層窗口時(shí),屬于它的所有窗口均為最頂層窗口,而它的所有者的z序并不改變?!?
  
  如果HWND_TOPMOST和HWND_NOTOPMOST標(biāo)志均未指定,即應(yīng)用程序要求窗口在激活的同時(shí)改變其在Z序中的位置時(shí),在參數(shù)hWndinsertAfter中指定的值只有在下列條件中才使用: 
  
  在hWndlnsertAfter參數(shù)中沒(méi)有設(shè)定HWND_NOTOPMOST和HWND_TOPMOST標(biāo)志?!?
  
  由hWnd參數(shù)標(biāo)識(shí)的窗口不是激活窗口?!?
  
  如果未將一個(gè)非激活窗口設(shè)定到z序的頂端,應(yīng)用程序不能激活該窗口。應(yīng)用程序可以無(wú)任何限制地改變被激活窗口在Z序中的位置,或激活一個(gè)窗口并將其移到最高級(jí)窗口的頂部或非最高級(jí)窗口的頂部?!?
  
  如果一個(gè)頂層窗口被重定位到z序的底部(HWND_BOTTOM)或在任何非最高序的窗口之后,該窗口就不再是最頂層窗口。當(dāng)一個(gè)最頂層窗口被置為非最頂級(jí),則它的所有者窗口和所屬者窗口均為非最頂層窗口?!?
  
  一個(gè)非最頂端窗口可以擁有一個(gè)最頂端窗口,但反之則不可以。任何屬于頂層窗口的窗口(例如一個(gè)對(duì)話框)本身就被置為頂層窗口,以確保所有被屬窗口都在它們的所有者之上。 
  
  如果應(yīng)用程序不在前臺(tái),但應(yīng)該位于前臺(tái),就應(yīng)調(diào)用SetForegroundWindow函數(shù)來(lái)設(shè)置。 
  
  Windows  CE:如果這是一個(gè)可見(jiàn)的頂層窗口,并且未指定SWP_NOACTIVATE標(biāo)志,則這個(gè)函數(shù)將激活窗口、如果這是當(dāng)前的激活窗口,并且指定了SWP_NOACTIVATE或SWP_HIDEWINDOW標(biāo)志,則激活另外一個(gè)可見(jiàn)的頂層窗口。 
  
  當(dāng)在這個(gè)函數(shù)中的nFlags參數(shù)里指定了SWP_FRAMECHANGED標(biāo)志時(shí),WindowsCE重畫(huà)窗口的整個(gè)非客戶區(qū),這可能會(huì)改變客戶區(qū)的大小。這也是重新計(jì)算客戶區(qū)的唯一途徑,也是通過(guò)調(diào)用SetwindowLong函數(shù)改變窗口風(fēng)格后通常使用的方法?!?
  SetWindowPos將使WM_WINDOWPOSCHANGED消息向窗口發(fā)送,在這個(gè)消息中傳遞的標(biāo)志與傳遞給函數(shù)的相同。這個(gè)函數(shù)不傳遞其他消息?!?
  
  Windows  CE  1.0不支持在hWndlnsertAber參數(shù)中的HWND_TOPMOST和HWND_NOTOPMOST常量。 
  
   Windows  CE1.0不支持在fuFags參數(shù)中的SWP_DRAWFRAME和SWP_NOCOPYBITS標(biāo)志?!?
  
  速查:Windows  NT:3.1以上版本;Windows:95以上版本;Windows  CE:1.0以上版本;頭文件:winuser.h庫(kù)文件:eser32lib?!?br />  
21. 介紹函數(shù)過(guò)程中一種任意鍵退出同時(shí)能處理消息的實(shí)現(xiàn)方法

1. 設(shè)置定時(shí)器,用于使::GetMessage(...)函數(shù)總能快速取到消息.
2. 在函數(shù)處理中加入:
函數(shù)每執(zhí)行完一步后執(zhí)行下面的代碼.

復(fù)制代碼 代碼如下:
if (::GetMessage(&msg, 0, 0, 0))
{
  if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) return ;
  ::TranslateMessage(&msg);
  ::DispatchMessage(&msg);
}
else ::PostQuitMessage(0);

22. 如何隱藏工具欄

添加如下兩個(gè)函數(shù)

隱藏:

復(fù)制代碼 代碼如下:
void CMainFrame::OnHide()
{
  if(m_wndToolBar.IsWindowVisible())
    m_wndToolBar.ModifyStyle(WS_VISIBLE,0);
  SendMessage(WM_SIZE);
}

顯示:
復(fù)制代碼 代碼如下:
void CMainFrame::OnShow()
{
  if(!m_wndToolBar.IsWindowVisible())
    m_wndToolBar.ModifyStyle(0,WS_VISIBLE);
  SendMessage(WM_SIZE);
}

23. 如何動(dòng)態(tài)獲取工具條指針并給工具條加標(biāo)題?

問(wèn)題提出:

工具條也是窗口,是窗口就有標(biāo)題,如何給工具條加標(biāo)題?

程序?qū)崿F(xiàn):

不想動(dòng)態(tài)改變工具條的標(biāo)題就在CMainFrame::OnCreate()中:

復(fù)制代碼 代碼如下:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
m_wndToolBar.SetWindowText(_T("Standdard"));
return 0;
}

若想動(dòng)態(tài)改變工具條的標(biāo)題,如下:
聲明一個(gè)菜單,并響應(yīng)事件,如響應(yīng):OnMyToolBar()函數(shù)
復(fù)制代碼 代碼如下:
void CMainFrame::OnMyToolBar()
{
// TODO: Add your command handler code here
CToolBar *pToolBar = (CToolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
pToolBar->SetWindowText (_T("Standdard"));
}

不要在TooBar懸浮時(shí)做OnMyToolBar()會(huì)出錯(cuò)的.
順便提一下如何獲得狀態(tài)條的指針:
復(fù)制代碼 代碼如下:
CStatusBar * pStatusBar =(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);

24. 在狀態(tài)條中顯示鼠標(biāo)的設(shè)備坐標(biāo)與邏輯坐標(biāo)

顯示器的設(shè)備坐標(biāo)系的原點(diǎn)在客戶區(qū)的左上角,x軸向右增長(zhǎng),y軸向下增長(zhǎng)。我們要設(shè)置的邏輯坐標(biāo)系的原點(diǎn)則在客戶區(qū)的中心,x軸向右增長(zhǎng),y軸向上增長(zhǎng),如一個(gè)笛卡爾坐標(biāo)系一般。
為CChildView添加一個(gè)成員函數(shù)void OnPrepareDC(CDC * pDC, CPrintInfo * pInfo = NULL);

復(fù)制代碼 代碼如下:
void OnPrepareDC(CDC * pDC, CPrintInfo * pInfo){
 CRect rect;
 // 設(shè)置映射模式為L(zhǎng)OMETRIC (0.1mm),右上為增長(zhǎng)方向
 pDC->SetMapMode (MM_LOMETRIC);
 // 將坐標(biāo)原點(diǎn)定在客戶區(qū)的中心
 GetClientRect(rect);
 pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);
}

為CChildView響應(yīng)鼠標(biāo)移動(dòng)消息,并在狀態(tài)條中顯示鼠標(biāo)的坐標(biāo)值。m_ptMouse數(shù)據(jù)成員是原打算做十字交叉線用的,在此使用沒(méi)有實(shí)際意義。
復(fù)制代碼 代碼如下:
void CChildView::OnMouseMove(UINT nFlags, CPoint point){
 CClientDC dc(this);
 CString str;
 OnPrepareDC(&dc);
 //要訪問(wèn)類CMainFrame,需要將mainfrm.h文件引入
 CMainFrame * pFrame = (CMainFrame *) AfxGetApp()->m_pMainWnd;
 //要訪問(wèn)CMainFrame的數(shù)據(jù)成員m_wndStatusBar,需要手工修改mainfrm.h,public這個(gè)數(shù)據(jù)成員
 CStatusBar * pStatus = (CStatusBar *) &pFrame->m_wndStatusBar;
 m_ptMouse = point;
 str.Format ("設(shè)備坐標(biāo) X=%i pixel, Y=%i pixel", m_ptMouse.x, m_ptMouse.y);
 pStatus->SetPaneText(1, str);
 dc.DPtoLP(&m_ptMouse);
 str.Format ("邏輯坐標(biāo) X=%i * 0.1mm, Y=%i * 0.1mm", m_ptMouse.x, m_ptMouse.y);
 pStatus->SetPaneText(2, str);
}

25. 如何用VC++ 動(dòng)態(tài)修改應(yīng)用程序菜單

問(wèn)題提出

  本文將介紹一些使用CMenu的方法,如查找指定菜單,在指定選項(xiàng)前添加菜單項(xiàng).....

解決方法

  使用CWnd::GetMenu( )訪問(wèn)主菜單,GetMenu( )返回指向CMenu對(duì)象的指針,它有一些成員函數(shù),允許我們修改一個(gè)菜單。

  1) 如何實(shí)現(xiàn)找到一個(gè)菜單項(xiàng):
  步驟如下:

復(fù)制代碼 代碼如下:
  {
     //動(dòng)態(tài)修改菜單:
     // 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);//菜單項(xiàng)的位數(shù).
     AfxMessageBox(s);
     ASSERT(pSubMenu);
  }

  2) 動(dòng)態(tài)編輯菜單:
  步驟如下(可以用上例的pSubMenu,要加的菜單你自己定義.):
  1) 添加一個(gè)稱為Wzd2,命令I(lǐng)D為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) 刪除該菜單中第二項(xiàng),可以用:
     pSubMenu->RemoveMenu(1,MF_BYPOSITION);
26. VC++中的3D按鈕的編程
運(yùn)行AppWizard生成一個(gè)基于對(duì)話框的test工程,在對(duì)話框中加入一個(gè)CButton控件。在CButton控件的General屬性頁(yè)將控件的ID改為IDC_3DTEXTBTN,Caption改為“誰(shuí)與爭(zhēng)瘋”,在控件Styles屬性頁(yè)選中OwnerDraw,其余設(shè)置保持默認(rèn)。
  用classwizard創(chuàng)建一個(gè)新類:C3dTextButton,基類為CButton。為C3dTextButton類添加一個(gè)protected的函數(shù)void Draw(CDC* pDC, const CRect& rect, UINT state)。如下所示編寫(xiě)代碼:
復(fù)制代碼 代碼如下:
  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;//寬度設(shè)為0,寬度值由高度確定
    logfont.lfWeight=1000;
    logfont.lfEscapement=logfont.lfOrientation=0;
    CFont tryfont; VERIFY(tryfont.CreateFontIndirect(&logfont));
    CFont* pFontOld=pDC->SelectObject(&tryfont);
    //根據(jù)控件大小,調(diào)整字體的高度,使文本與控件協(xié)調(diào)
    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);
    }
    //創(chuàng)建并選擇協(xié)調(diào)后的字體
    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;
 
    //實(shí)現(xiàn)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);
 
    //輸出標(biāo)題
    pDC->TextOut(cx,cy,text);
 
    //恢復(fù)設(shè)備描述表
    pDC->SetTextColor(oldTextColor);
    pDC->SetBkMode(oldBkMode);
    pDC->SelectObject(pFontOld);
  }

  用classwizard重載C3dTextButton類的DrawItem函數(shù)。編寫(xiě)代碼如下所示:
復(fù)制代碼 代碼如下:
  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建立一個(gè)C3dTextButton控件變量m_3dTextButton1。

把“3dTextButton.h”加入testDlg頭文件。編譯并測(cè)試應(yīng)用程序。

27. 如何正確的得到ComBox的指針

復(fù)制代碼 代碼如下:
CComboBox *mComb = (CComboBox*)GetDlgItem(IDC_DuanCB);
CComboBox *mComb = (CComboBox*)::GetDlgItem(m_hWnd,IDC_DuanCB);

28. 如何讓對(duì)話框中的CEdit控件類接收對(duì)話框的消息
////////////////////////////////////////////////
// 如何讓對(duì)話框中的CEdit控件類接收對(duì)話框的消息
////////////////////////////////////////////////
1、在對(duì)話框中增加一個(gè)ID 為IDC_EDIT1的CEdit1控件
2、通過(guò)ClassWizard 生成一個(gè)基于CEdit的新類CMyEdit,
復(fù)制代碼 代碼如下:
CMyEdit m_wndEdit;

3、在對(duì)話框OnInitDialog()中,將m_wndEdit子類化,使其能夠接受對(duì)話框的消息。
復(fù)制代碼 代碼如下:
m_wndEdit.SubclassDlgItem (IDC_EDIT1,this);

29.利用WM_CTLCOLOR消息實(shí)現(xiàn)編輯控制(Edit Control)的文本與背景色的改變
首先要明白:WM_CTLCOLOR是一個(gè)由控制(Control)發(fā)送給它父窗口的通知消息(Notification message)。

實(shí)現(xiàn)步驟:

生成一個(gè)標(biāo)準(zhǔn)的單文檔應(yīng)用程序框架,假設(shè)應(yīng)用程序的名稱為Color。我將利用它的About對(duì)話框做示范。在About dialog中添加兩個(gè)Edit control,設(shè)定其ID為IDC_EDIT1與IDC_EDIT2。

第一種方法(對(duì)應(yīng)于IDC_EDIT1): 按照標(biāo)準(zhǔn)的Windows編程,由其父窗口的消息處理函數(shù)負(fù)責(zé)處理WM_CTLCOLOR消息。

1. 在CAboutDlg中添加一個(gè)數(shù)據(jù)成員:HBRUSH m_brMine;
2. 利用向?qū)в成銩boutDlg的WM_CTLCOLOR消息,產(chǎn)生函數(shù):HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
pDC是AboutDlg的設(shè)備上下文,pWnd是AboutDlg中發(fā)送該消息的control指針,nCtlColor市Control的類型編碼。對(duì)其進(jìn)行如下修改:

復(fù)制代碼 代碼如下:
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);  //設(shè)置紅色的文本
   clr = RGB(0,0,0);
   pDC->SetBkColor(clr);   //設(shè)置黑色的背景
   m_brMine = ::CreateSolidBrush(clr);
   return m_brMine; //作為約定,返回背景色對(duì)應(yīng)的刷子句柄
 }
 else
 {
   HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
   return hbr;
 }
}

第二種方法(對(duì)應(yīng)于IDC_EDIT2):

利用MFC 4.0的新特性: Message reflection。

1.利用向?qū)砑右粋€(gè)新的類:CColorEdit,基類為CEdit;
2.在CColorEdit中添加一個(gè)數(shù)據(jù)成員: HBRUSH m_bkBrush;
3.利用向?qū)в成銫ColorEdit的=WM_CTLCOLOR消息,產(chǎn)生函數(shù):

復(fù)制代碼 代碼如下:
HBRUSH CColorEdit::CtlColor(CDC* pDC, UINT nCtlColor);

對(duì)其進(jìn)行如下修改:
復(fù)制代碼 代碼如下:
HBRUSH CColorEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
 COLORREF clr = RGB(0,0,0);
 pDC->SetTextColor(clr);  //設(shè)置黑色的文本
 clr = RGB(255,0,0);
 pDC->SetBkColor(clr);   //設(shè)置紅色的背景
 m_bkBrush = ::CreateSolidBrush(clr);
 return m_bkBrush; //作為約定,返回背景色對(duì)應(yīng)的刷子句柄
}

4.利用向?qū)镮DC_EDIT2生成一個(gè)數(shù)據(jù)成員CColorEdit m_coloredit;
5.在定義CAboutDlg的color.cpp文件中加入:#include "coloredit.h"
30. 如何防止密碼被非法獲取?

問(wèn)題提出

  這兩天大家比較專注在獲取Edit密碼框的密碼.在盜取時(shí),我們?nèi)绾畏婪赌?#63;
 
解決方法

  此方法針對(duì)于通過(guò)SendMessage向此窗口發(fā)送WM_GETTEXT或EM_GETLINE消息來(lái)取得密碼.跟我來(lái).
 
程序?qū)崿F(xiàn)

  方法很簡(jiǎn)單,用CWnd::DefWindowProc函數(shù)攔截得到的消息(向Edit發(fā)的).
  建立名為My的對(duì)話框工程.建立一個(gè)Edit控件ID=IDC_EDIT1.建一個(gè)新類名為CMyProtectEdit,派生于CEdit.
  在MyDlg.cpp中聲明全局變量:BOOL g_bIdentity;

復(fù)制代碼 代碼如下:
  BOOL g_bIdentity;
  在MyProtecEdit.cpp中:
  extern BOOL g_bIdentity;
  響應(yīng)CMyProtectEdit的DefWindowProc函數(shù):
  LRESULT CMyProtectEdit::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  {
    // TODO: Add your specialized code here and/or call the base class
    // 對(duì)Edit的內(nèi)容獲取必須通過(guò)以下兩個(gè)消息之一,不對(duì)其采用默認(rèn)的處理:
    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中
復(fù)制代碼 代碼如下:
  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
  }

  即可.找個(gè)程序(盜取)的試試.

31. 如何在編輯控件中以追加的方式添入字符?

問(wèn)題提出:
  SetDlgItemText可以向Edit控件中輸入字符,發(fā)送更新的消息也可是Edit控件顯示與其關(guān)聯(lián)的變量的值,但若是向已有的Edit字符后追加字符,該如何做?

程序?qū)崿F(xiàn):

  建立名為My的對(duì)話框工程,添加一個(gè)Edit和一個(gè)Button控件.Edit的ID=IDC_EDIT1,Button的ID=IDC_BUTTON1.建立和IDC_BUTTON1的響應(yīng)函數(shù):OnButton1()

復(fù)制代碼 代碼如下:
  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控件中輸入字符,想追加時(shí)按IDC_BUTTON1按鈕.看看效果.

32.屬性頁(yè)標(biāo)題改名

我用CPropertySheet創(chuàng)建屬性頁(yè),用的CPropertyPage對(duì)象只有一個(gè),也就是每個(gè)屬性頁(yè)的內(nèi)容一樣.現(xiàn)在的問(wèn)題是:這樣每個(gè)屬性頁(yè)的標(biāo)題都是一樣的,是對(duì)話框的標(biāo)題!怎樣動(dòng)態(tài)的改變這個(gè)標(biāo)題,使每個(gè)屬性頁(yè)的標(biāo)簽的名稱都不同??

復(fù)制代碼 代碼如下:
CTabCtrl * pCtrl = pSheet->GetTabControl();
TCITEM tc;
tc.mask = TCIF_TEXT;
tc.pszText = "新標(biāo)題";
pCtrl->SetItem(0,&tc);//0即是你要改的TAb的索引

33. 怎樣去掉屬性頁(yè)的Apply與Help按鈕?
復(fù)制代碼 代碼如下:
//去掉Help
  m_psh.dwFlags |= PSH_HASHELP ;
  m_psh.dwFlags &= ~PSH_HASHELP ;
//除掉應(yīng)用按鈕 m_psh.dwFlags|=PSH_NOAPPLYNOW;

34. 如何給樹(shù)控件加入工具提示
1.首先給樹(shù)控件加入TVS_INFOTIP屬性風(fēng)格,如下所示:
復(fù)制代碼 代碼如下:
if (!m_ctrlTree.Create(WS_CHILD|WS_VISIBLE|
  TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT|TVS_SHOWSELALWAYS|TVS_INFOTIP, //加入提示TVS_INFOTIP,jingzhou xu(樹(shù)控件ID:100)
   CRect(0, 0, 0, 0), &m_wndTreeBar, 100))
  {
   TRACE0("Failed to create instant bar child\n");
   return -1;
  }

2.其次加入映射消息聲明,如下所示:
復(fù)制代碼 代碼如下:
afx_msg void OnGetInfoTip(NMHDR* pNMHDR,LRESULT* pResult);  //樹(shù)控件上加入提示消息,jingzhou xu  
ON_NOTIFY(TVN_GETINFOTIP, 100, OnGetInfoTip) //樹(shù)控件條目上加入提示,jingzhou xu

3.最后加入呼應(yīng)涵數(shù)處理:
復(fù)制代碼 代碼如下:
void CCreateTreeDlg::OnGetInfoTip(NMHDR* pNMHDR,
                  LRESULT* pResult)
 {
 *pResult = 0;
 NMTVGETINFOTIP* pTVTipInfo = (NMTVGETINFOTIP*)pNMHDR;
 LPARAM itemData = (DWORD) pTVTipInfo->lParam;
 //對(duì)應(yīng)每個(gè)條目的數(shù)據(jù)
 HTREEITEM hItem = pTVTipInfo->hItem;
 CString tip;
 HTREEITEM hRootItem = m_chassisTree.GetRootItem();
 if (hRootItem != pTVTipInfo->hItem)
 {
  tip = "樹(shù)結(jié)點(diǎn)的提示";
 }
 else
 {
  tip = "樹(shù)根上的提示";
 }
 strcpy(pTVTipInfo->pszText, (LPCTSTR) tip);
}

35. 如何在TreeList中加圖標(biāo)?

問(wèn)題提出:

 請(qǐng)問(wèn)treeview控件和treectrl控件的用法有何不同呢?向如何imagelist控件中加圖象呀?

解決方法:
 1)

復(fù)制代碼 代碼如下:
  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)
復(fù)制代碼 代碼如下:
  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));
  //設(shè)置圖象列表
  m_list.SetImageList(&cil1,LVSIL_NORMAL);

36. 如何雙擊列表框項(xiàng)啟動(dòng)一個(gè)與文件關(guān)聯(lián)的程序?

有人問(wèn)我如何雙擊列表框項(xiàng)啟動(dòng)一個(gè)程序?其實(shí)這個(gè)問(wèn)題很簡(jiǎn)單,Windows中有一個(gè)API函數(shù)可以打開(kāi)任何類型的文件:

復(fù)制代碼 代碼如下:
ShellExecute(NULL,"open",lpFileName,NULL,NULL,SW_SHOWNORMAL);

參數(shù) lpFileName 是文件的全路徑名。用這個(gè)變量你可以傳遞象“C:\\MyExcelFile.xls”或者“http://www.vckbase.com”啟動(dòng)Excel程序或者瀏覽器程序。如果你只是想獲取與文件關(guān)聯(lián)的程序名,而不是要運(yùn)行程序,那么調(diào)用::FindExecutable就可以了。

37. 如何防止在listbox中添加很多數(shù)據(jù)出現(xiàn)不停的刷新?

問(wèn)題提出:

  在listbox添加很多數(shù)據(jù)的時(shí)候,由于控件不停的刷新,導(dǎo)致出現(xiàn)閃爍,如何解決?

解決方法:

  再添加數(shù)據(jù)以前,禁止控件刷新,數(shù)據(jù)添加完畢以后,再刷新一次。

程序?qū)崿F(xiàn):
(其中:m_ListBox是CListBox的控件類型的變量)

復(fù)制代碼 代碼如下:
  m_ListBox.LockWindowUpdate();//禁止本listbox刷新。
  for(int i=0;i<9999;i++)
  {
     m_ListBox.AddString("test");
  }//添加數(shù)據(jù)。
  this->RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);

38. 如何得到CListBox所選擇項(xiàng)的String?

問(wèn)題提出:

 如何得到CListBox所選擇項(xiàng)的String

解決方法:

 用到:CListBox::GetText()

程序?qū)崿F(xiàn):

復(fù)制代碼 代碼如下:
 CString scInfo;
 pList->GetText( GetCurSel(),scInfo);

39. 用鼠標(biāo)移動(dòng)基于對(duì)話框的無(wú)標(biāo)題欄程序的簡(jiǎn)單方法
復(fù)制代碼 代碼如下:
void CVCTestDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
  //一句話解決問(wèn)題
  SendMessage(WM_SYSCOMMAND,0xF012,0);
  CDialog::OnLButtonDown(nFlags, point);
}

40. 如何改變框?qū)υ捇虼绑w視窗的背景顏色

調(diào)用CWinApp : : SetDialogBkColor可以改變所有應(yīng)用程序的背景顏色。第一個(gè)參數(shù)指定了背景顏色,第二個(gè)參數(shù)指定了文本顏色。下例將應(yīng)用程序?qū)υ捲O(shè)置為藍(lán)色背景和黃色文本。

復(fù)制代碼 代碼如下:
BOOL CSampleApp : : InitInstance ( )
{

//use blue dialog with yellow text .
SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 , 255 , 0 ) ) ;

}

需要重畫(huà)對(duì)話(或?qū)υ挼淖涌丶?時(shí),Windows向?qū)υ挵l(fā)送消息WM_CTLCOLOR,通常用戶可以讓W(xué)indows選擇繪畫(huà)背景的刷子,也可重置該消息指定刷子。下例說(shuō)明了創(chuàng)建一個(gè)紅色背景對(duì)話的步驟。
首先,給對(duì)話基類增加一人成員變量CBursh :
復(fù)制代碼 代碼如下:
class CMyFormView : public CFormView
{

private :
CBrush m_ brush ; // background brush

} ;

其次, 在類的構(gòu)造函數(shù)中將刷子初始化為所需要的背景顏色。
復(fù)制代碼 代碼如下:
CMyFormView : : CMyFormView ( )
{
// Initialize background brush .
m_brush .CreateSolidBrush (RGB ( 0, 0, 255 ) )
}

最后,使用ClassWizard處理WM_CTLCOLOR消息并返回一個(gè)用來(lái)繪畫(huà)對(duì)話背景的刷子句柄。注意:由于當(dāng)重畫(huà)對(duì)話控件時(shí)也要調(diào)用該函數(shù),所以要檢測(cè)nCtlColor參量。
復(fù)制代碼 代碼如下:
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 );
}

41.如何禁止對(duì)話框關(guān)閉按鈕和浮動(dòng)工具條上的系統(tǒng)菜單
1、禁止對(duì)話框中的關(guān)閉按鈕有二種方法。
第一種方法,用ModiftMenu()涵數(shù)來(lái)實(shí)現(xiàn):

復(fù)制代碼 代碼如下:
CMenu* pMenu = this->GetSystemMenu(FALSE);
pMenu->ModifyMenu(SC_CLOSE,MF_BYCOMMAND | MF_GRAYED );

第二種方法,用EnableMenuItem()涵數(shù)來(lái)實(shí)現(xiàn):
復(fù)制代碼 代碼如下:
CMenu* pMenu = this->GetSystemMenu(FALSE);
pMenu->EnableMenuItem( SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);

2、禁止浮動(dòng)工具條上的系統(tǒng)菜單。
新建一個(gè)CToolBar的派生類CxxToolBar,在新類中的左鍵雙擊(CxxToolBar::OnLButtonDblClk(...))
和左鍵單擊(CxxToolBar:: OnLButtonDown(...))涵數(shù)中分別加入下面代碼既可:
復(fù)制代碼 代碼如下:
if (IsFloating()) //工具條正在浮動(dòng)狀態(tài)中
{
  CWnd* pMiniFrame;
  CWnd* pDockBar;
  pDockBar = GetParent();
  pMiniFrame = pDockBar->GetParent();
  //去除其上系統(tǒng)菜單
  pMiniFrame->ModifyStyle(WS_SYSMENU, NULL);
  //重繪工具條
  pMiniFrame->ShowWindow(SW_HIDE);
  pMiniFrame->ShowWindow(SW_SHOW);
}

3、禁止窗口最大化按鈕
在PreCreateWindow()涵數(shù)中去掉WS_MAXIMIZEBOX風(fēng)格顯示既可。
復(fù)制代碼 代碼如下:
BOOL CxxFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
  cs.style &= ~WS_MAXIMIZEBOX;
  return CFrameWnd::PreCreateWindow(cs);
}

42.如何拷貝一個(gè)工程的對(duì)話框資源到另一個(gè)工程中?

有兩種方法可以實(shí)現(xiàn):
 
 1)你可以直接拷貝resource,用VC++以文本的方式或者直接用文本編輯器打開(kāi).rc文件,將有關(guān)的片段從
一個(gè)工程拷貝到另一個(gè)工程.你可以通過(guò)查找如下字樣的片段(此片段用來(lái)定義對(duì)話框資源)來(lái)拷貝你要
的部分:

復(fù)制代碼 代碼如下:
 IDD_MYDIALOG_ID DIALOG DISCARDABLE 0, 0, 235, 55

 
 這里的IDD_MYDIALOG_ID是你的對(duì)話框的ID,將到此片段結(jié)尾的部分全拷下來(lái),通常你還要給新的工程
加一個(gè)ID(通過(guò)DevStudio的工具或者直接修改resource.h文件).
 2)可以通過(guò)DevStudio的copy/paste功能.首先,在編輯器以"auto"模式打開(kāi).rc文件,這時(shí)resource
正確的顯示出來(lái).然后,選中要拷貝的對(duì)話框的ID,在Edit菜單里選Copy或者按住Ctrl+C.然后打開(kāi)目標(biāo)
resource文件,在Edit菜單里選Paste或者按住Ctrl+V.
43.如何實(shí)現(xiàn)點(diǎn)一下對(duì)話框外面的區(qū)域,自動(dòng)隱藏對(duì)話框?

問(wèn)題提出:

  如果想在點(diǎn)擊對(duì)話框外面的地方使得對(duì)話框關(guān)閉,該如何做?

解決方法:

  試試下面的代碼,原理是在激活對(duì)話框時(shí),捕獲鼠標(biāo)的動(dòng)作,當(dāng)鼠標(biāo)點(diǎn)擊時(shí)判斷是否點(diǎn)擊在對(duì)話框外,是的話就釋放對(duì)話框.

程序?qū)崿F(xiàn):

  建立名為My的對(duì)話框程序.實(shí)現(xiàn)如下步驟:
  在MyDlg.h中加入:

復(fù)制代碼 代碼如下:
  class CShowWindow1Dlg : public CDialog
  {
   // Construction
   public:
     int m_cx;
     int m_cy;
     ......
  };

  在MyDlg.cpp中:
復(fù)制代碼 代碼如下:
  //定義消息映象,處理鼠標(biāo)單擊及激活
  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);
      }
    }
  }

   說(shuō)明:
   1)WM_ACTIVATE消息在ClassWizard中沒(méi)有,按如下步驟添加,右擊CMyDlg類,選Add Windows Message Handle,接著在Filter for messages available to中選Window,在New Windows messages/events列表中就會(huì)出現(xiàn)WM_ACTIVATE,選中,點(diǎn)擊Add Handler
   2)SM_CXDLGFRAME,SM_CYDLGFRAME  NT中取得有WS_DLGFRAMEstyle風(fēng)格的窗口的高和寬 95中已經(jīng)廢棄而采用SM_CX_FIXEDFRAME和SM_CYFIXEDFRAME

44. 初始化應(yīng)用程序的大小

如果想使應(yīng)用程序界面(文檔)在開(kāi)始運(yùn)行是按你的尺寸展現(xiàn)在屏幕上,

添加代碼如下:

復(fù)制代碼 代碼如下:
 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是你的初始界面占屏幕的百分比,可以自己修改。如果想使應(yīng)用程序大小固定添加cs.style&=~WS_THICKFRAME;
45. 如何得到視圖指針?

問(wèn)題提出:

  現(xiàn)在你有一個(gè)多線程的Demo,你想在多線程里處理視圖指針里的函數(shù),我們給這個(gè)函數(shù)起個(gè)名字:Put();該如何實(shí)現(xiàn)呢?

復(fù)制代碼 代碼如下:
  //有兩種方法可以實(shí)現(xiàn)你的要求:
  //1)第一種方法:
  //要是多線程不是在App.cpp里出現(xiàn),那么要在多線程的.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);
  //調(diào)用視圖函數(shù):
  m_pview->Put();
  //2)第二種方法:
  //獲得窗體指針:
  CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;
  //獲得與該窗體符合的視圖:
  CYourView *m_pView = (CYourView *) pFrame->GetActiveView();
  //調(diào)用視圖函數(shù):
  m_pView->Put();

46. 如何使我的程序在啟動(dòng)時(shí)不創(chuàng)建一個(gè)新文檔?

問(wèn)題:

如何使我的程序在啟動(dòng)時(shí)不創(chuàng)建一個(gè)新文檔?

解答:

在程序的InitInstance中的ProcessShellCommand函數(shù)之前加入:

復(fù)制代碼 代碼如下:
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing

47. 如何將標(biāo)題欄上的右鍵菜單屏蔽掉?

解決方法:

  右鍵菜單是系統(tǒng)菜單,只要將其WS_SYSMENU的屬性去掉即可.

程序?qū)崿F(xiàn):

復(fù)制代碼 代碼如下:
  int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
  {
     ........
  long style = GetWindowLong(m_hWnd, GWL_STYLE);
     style &= ~WS_SYSMENU;
     SetWindowLong(m_hWnd, GWL_STYLE, style);
  return 0;
  }

48.如何全屏顯示(沒(méi)有標(biāo)題,沒(méi)有菜單,沒(méi)有工具條)

解決方法:

  重載CMainFrame的ActivateFrame函數(shù):

復(fù)制代碼 代碼如下:
  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.如何設(shè)置有背景顏色的文本
(1)解決方法
  用到了CDC::SetBkMode();
 
程序?qū)崿F(xiàn)
復(fù)制代碼 代碼如下:
  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,并響應(yīng)WM_ERASEBKGND.
復(fù)制代碼 代碼如下:
  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.串太長(zhǎng)時(shí)往讓其末尾顯示一個(gè)省略號(hào)(在SDI或MDI的View中)

問(wèn)題提出:

  如何在串太長(zhǎng)時(shí)往讓其末尾顯示一個(gè)省略號(hào)(在SDI或MDI的View中)?

程序?qū)崿F(xiàn):

  建立名為My的SDI或MDI工程.

復(fù)制代碼 代碼如下:
  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);
  }

51. 如何獲得其他程序的圖標(biāo),并顯示在View中

問(wèn)題提出:

 有的時(shí)候,如:類資源管理器會(huì)遇到獲得程序圖標(biāo)并顯示的操作,如何實(shí)現(xiàn)呢?

解決方法:

 SDK函數(shù)SHGetFileInfo來(lái)獲得有關(guān)文件的很多信息:如大小圖標(biāo),屬性,類型等.

程序?qū)崿F(xiàn):

 建立名為My的SDI工程.在OnPaint()函數(shù)中加入:

復(fù)制代碼 代碼如下:
 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
 }

 說(shuō)明:_T("NotePad.exe")指的是要獲得什么程序的圖標(biāo).
 或者在OnDraw()中(此時(shí)必須保證沒(méi)有OnPaint()函數(shù),想想為何?)
復(fù)制代碼 代碼如下:
 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中打開(kāi))中加入CRichEdit控件后,這個(gè)dialog 為什么打不開(kāi)如何處理?

解決方法:

 在函數(shù):InitInstance的第一句加入AfxInitRichEdit();
53. 如何使FormView中顯示dialog時(shí),不是凹的?

問(wèn)題提出:

 為什么FormView中顯示dialog時(shí),是凹的,能不能不這樣

解決方法:

 在Dialog的屬性中:
  增加屬性WS_BORDER  或者 WS_EX_WINDOWEDGE
 用程序?qū)崿F(xiàn):
 pView->ModifyStyle(,WS_BORDER) 或者pView->ModifyStyleEx(,WS_EX_WINDOWEDGE )

54. 如何改變窗口標(biāo)題?

問(wèn)題提出:

  在應(yīng)用程序的不同運(yùn)行時(shí)期,要反映當(dāng)前狀態(tài)往往會(huì)修改應(yīng)用程序標(biāo)題.

解決方法:

  在MFC類庫(kù)中提供了CWnd::SetWindowText函數(shù),通過(guò)該函數(shù)可以改變?nèi)魏未绑w(包括控件)的標(biāo)題.
  改變主窗體的標(biāo)題:

復(fù)制代碼 代碼如下:
  CWnd *m_pMainWnd;
  m_pMainWnd=AfxGetMainWnd();
  m_pMainWnd->SetWindowText(_T("改變標(biāo)題"));

  當(dāng)改變多視MDI的子窗口的標(biāo)題時(shí),用:
復(fù)制代碼 代碼如下:
GetParentFrame()->SetWindowText(_T("MDI Child改變標(biāo)題"));

  當(dāng)改變按鈕的標(biāo)題時(shí)(假設(shè)按鈕的ID=IDC_BUTTON1):
復(fù)制代碼 代碼如下:
GetDlgItem(IDC_BUTTON1)->SetWindowText(_T("Button 改變標(biāo)題"));

  運(yùn)行看看.
55.圖標(biāo)透明

(1).Windows中的圖標(biāo)其實(shí)是有兩個(gè)圖像組成的,其中一個(gè)用于與它要顯示的位置的圖像做“AND”操作,另一個(gè)作“XOR”操作。
透明:用“白色”AND,用“黑色”XOR
反色:用“白色”AND,用“白色”XOR
正常色:用“黑色”AND,用正常顏色XOR.

(2). WIN9X中好像是對(duì)像素的操作實(shí)現(xiàn)透明的
WIN2K中就有API直接實(shí)現(xiàn)透明了!
WIN2K中
GetWindowLong
SetWindowLong
SetLayeredWindowAttributes

三個(gè)API就可以實(shí)現(xiàn)透明了!
(3)

復(fù)制代碼 代碼如下:
::DrawIconEx(pDC->GetSafeHdc(),point.x,point.y,icon,icosize,icosize,0,NULL,DI_NORMAL);

56.ASSERT()是干什么用的

ASSERT()是一個(gè)調(diào)試程序時(shí)經(jīng)常使用的宏,在程序運(yùn)行時(shí)它計(jì)算括號(hào)內(nèi)的表達(dá)式,如果表達(dá)式為FALSE (0), 程序?qū)?bào)告錯(cuò)誤,并終止執(zhí)行。如果表達(dá)式不為0,則繼續(xù)執(zhí)行后面的語(yǔ)句。這個(gè)宏通常原來(lái)判斷程序中是否出現(xiàn)了明顯非法的數(shù)據(jù),如果出現(xiàn)了終止程序以免導(dǎo)致嚴(yán)重后果,同時(shí)也便于查找錯(cuò)誤。例如,變量n在程序中不應(yīng)該為0,如果為0可能導(dǎo)致錯(cuò)誤,你可以這樣寫(xiě)程序:
  ......
  ASSERT( n != 0);
  k = 10/ n;
  ......
  ASSERT只有在Debug版本中才有效,如果編譯為Release版本則被忽略。
  assert()的功能類似,它是ANSI C標(biāo)準(zhǔn)中規(guī)定的函數(shù),它與ASSERT的一個(gè)重要區(qū)別是可以用在Release版本中。

56. 將RADIO控件初始狀態(tài)設(shè)置成為選中

1、在OnInitialDialog中用CButton::CheckRadioButton(...)
2、在OnInitialDialog中用CButton::SetCheck(...)
3、關(guān)聯(lián)一個(gè)整型值,在構(gòu)造函數(shù)中設(shè)為0。

57.獲得視圖

復(fù)制代碼 代碼如下:
CFrameWnd* pFrameWnd = (CFrameWnd*)theApp.GetMainWnd();
CMyView* pView = (CMyView*)pFrameWnd->GetActiveView();

58.如何得到屏幕的真實(shí)尺寸

問(wèn)題提出:

我的屏幕是1024*800,如何得到屏幕的真實(shí)大小,我用GetSystemMetrics(SM_CYFULLSCREEN)得到的高度總是小于800

問(wèn)題解答:

GetSystemMetrics(SM_CYFULLSCREEN)得到的只是屏幕用戶區(qū)的大小。要得到屏幕的真實(shí)大小需要使用
GetDeviceCaps函數(shù),該API函數(shù)原型是這樣的:

復(fù)制代碼 代碼如下:
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. 修改標(biāo)題欄高度

NONCLIENTMETRICS nm
調(diào)用SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(nm),&nm,0)
重設(shè)SystemParametersInfo(SPI_SETNONCLIENTMETRICS,sizeof(nm),&nm,0)

60. 如何實(shí)現(xiàn)“氣球式”工具提示。

本程序介紹一個(gè)與CToolTipCtrl相似的類CTooolTipWnd。
使用該類的方法如下:

1. 增加ToolTipWnd.cpp到工程文件。
2. 在頭文件中添加#include "ToolTipWnd.h" 。 
3. 在類聲明中添加:
CToolTipWnd m_BalloonToolTip;
4. 在OnInitDialog(對(duì)話框)或OnInitialUpdate(表單視)中添加下面代碼:

復(fù)制代碼 代碼如下:
  m_BalloonToolTip.Create(this);
  m_BalloonToolTip.AddTool(GetDlgItem(), , [text color]);
eg.
  m_BalloonToolTip.AddTool(GetDlgItem(IDC_EDIT1),"Tooltip", RGB(255,0,0));

  第三個(gè)參數(shù)為可選,缺省為RGB(0, 0, 0)。缺省文本顏色可以用SetDefTextColor進(jìn)行設(shè)置。
4. 重載PreTranslateMessage并添加下面代碼:
復(fù)制代碼 代碼如下:
  if(m_BalloonToolTip) 
    m_BalloonToolTip.RelayEvent(pMsg);

61. dlg 上建立View的方法:

復(fù)制代碼 代碼如下:
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. 窗口最大化、最小化及關(guān)閉的消息是什么?如何截獲?
最大化、最小化將發(fā)送WM_SYSCOMMAND消息。要處理該消息,可以這么做:
  1、在Form的頭文件中添加:
復(fù)制代碼 代碼如下:
   void __fastcall RestrictMinimizeMaximize(TMessage &Msg);
  
   BEGIN_MESSAGE_MAP
   MESSAGE_HANDLER(WM_SYSCOMMAND, TMessage, RestrictMinimizeMaximize)
   END_MESSAGE_MAP(TForm)

  2、在Form的單元文件中添加:
復(fù)制代碼 代碼如下:
   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
   }

  關(guān)閉窗口的消息為WM_CLOSE,C++Builder提供了OnClose事件。
63. 如何遍歷整個(gè)目錄樹(shù)查找文件
  
在應(yīng)用程序的開(kāi)發(fā)過(guò)程中,會(huì)遇到如何查找某一文件以確定此文件路徑的問(wèn)題。利用CFileFind類可以比較方便地在當(dāng)前目錄下進(jìn)行文件查找,但卻不能對(duì)其子目錄中的文件進(jìn)行搜尋。而實(shí)際應(yīng)用中往往需要對(duì)某一整個(gè)目錄樹(shù),甚至是整個(gè)C盤或D盤驅(qū)動(dòng)器進(jìn)行文件搜尋。通過(guò)實(shí)踐,我們?cè)赩isual C++ 6.0中編程實(shí)現(xiàn)了如何遍歷任意目錄樹(shù),以查找某一特定的文件。

  在下面的具體陳述中可以看到,在確定要查找的文件名和要進(jìn)行搜索的目錄的名稱后,將調(diào)用函數(shù)Search_Directory進(jìn)行文件的查找。首先依次查找當(dāng)前目錄下的每一個(gè)實(shí)體(文件或是子目錄),如果是某一子目錄,則進(jìn)入該子目錄并遞歸調(diào)用函數(shù)Search_Dirctory進(jìn)行查找,查找完畢之后, 再返回上一級(jí)目錄;如果不是子目錄而是某一文件,則判斷其是否就是我們要查找的文件,如果是則輸出其完整的文件路徑。這樣,通過(guò)Search_Directory函數(shù)的反復(fù)遞歸調(diào)用,就可以實(shí)現(xiàn)對(duì)整個(gè)目錄,包括子目錄的遍歷搜索。下面將舉例詳細(xì)講述如何在VC++中編程實(shí)現(xiàn)在整個(gè)目錄樹(shù)中的文件查找。

  1. 在Visual C++ 6.0(VC++ 5.0與之類似)中用默認(rèn)方式創(chuàng)建了一基于對(duì)話框的應(yīng)用程序Search。在主窗口對(duì)話框上放置一命令按鈕,其Caption為“Search File”,ID為ID_BUTTON_SEARCH。單擊此按鈕將完成文件的查找工作。

  2. 利用ClassWizard為“Search File”按鈕的BN_CLICKED 事件添加處理函數(shù)OnButtonSearch,代碼如下:

復(fù)制代碼 代碼如下:
#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:\\"); // 進(jìn)入要查找的路徑(也可為某一具體的目錄)
  // 查找文件, 如果查到則顯示文件的路徑全名
  Search_Directory(szFilename);
  // 為CSearchDlg類的一成員函數(shù)
  MessageBox(″查找文件完畢!″);
  // 顯示查找完畢的信息
}

  3. 在CSearchDlg類中增加成員函數(shù)Search_Directory,它將完成具體的文件查找工作,代碼如下:

復(fù)制代碼 代碼如下:
void CSearchDlg::Search_Directory(char* szFilename)
{
  long handle;
  struct _finddata_t filestruct;
  //表示文件(或目錄)的信息
  char path_search[_MAX_PATH];
  //表示查找到的路徑結(jié)果
  // 開(kāi)始查找工作, 找到當(dāng)前目錄下的第一個(gè)實(shí)體(文件或子目錄),
  // "*"表示查找任何的文件或子目錄, filestruct為查找結(jié)果
  handle = _findfirst("*", &filestruct);
  // 如果handle為-1, 表示當(dāng)前目錄為空, 則結(jié)束查找而返回
  if((handle == -1)) return;
  // 檢查找到的第一個(gè)實(shí)體是否是一個(gè)目錄(filestruct.name為其名稱)
  if( ::GetFileAttributes(filestruct.name) & FILE_ATTRIBUTE_DIRECTORY )
  {
   // 如果是目錄, 則進(jìn)入該目錄并遞歸調(diào)用函數(shù)Search_Dirctory進(jìn)行查找,
   // 注意: 如果目錄名的首字符為'.'(即為"."或".."), 則不用進(jìn)行查找
   if( filestruct.name[0] != '.' )
   {
     _chdir(filestruct.name);
     Search_Directory(szFilename);
     // 查找完畢之后, 返回上一級(jí)目錄
     _chdir("..");
   }
  }
  else // 如果第一個(gè)實(shí)體不是目錄, 則檢查是否是要查找的文件
  {
   // stricmp對(duì)兩字符串進(jìn)行小寫(xiě)形式的對(duì)比, 返回為0表示完全一致
   if( !stricmp(filestruct.name, szFilename) )
   {
     // 先獲得當(dāng)前工作目錄的全路徑
     _getcwd(path_search,_MAX_PATH);
     // 再獲得文件的完整的路徑名(包含文件的名稱)
     strcat(path_search,"\\");
     strcat(path_search,filestruct.name);
     MessageBox(path_search); //輸出顯示
   }
  }
  // 繼續(xù)對(duì)當(dāng)前目錄中的下一個(gè)子目錄或文件進(jìn)行與上面同樣的查找
  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);
  // 最后結(jié)束整個(gè)查找工作
}

  這樣我們就可以對(duì)整個(gè)目錄進(jìn)行遍歷搜索,查找某一特定的文件,并輸出顯示其完整的文件路徑。以上的程序在Visual C++ 6.0中已調(diào)試通過(guò)。

64. Richedit control的設(shè)置背景圖片辦法

1:繼承CRichEditCtrl::OnEraseBkgnd(CDC* pDC)消息事件中,給Richedit控件繪制上背景圖片:m_bmpBackground.DrawDIB(pDC, 0, 0, rc.Width(), rc.Height());當(dāng)然也可以通過(guò)subclass richedit window之后,在回調(diào)函數(shù)中處理WM_ERASEBKGND消息。

2:設(shè)置了Richedit控件的透明屬性;

3:依照kenwhale所說(shuō)的,Hook了GDI32.DLL中的ExtTextOut函數(shù),將RichEdit的text-output options去除ETO_OPAQUE style

。綜上所述,即可實(shí)現(xiàn)RichEdit控件的背景圖片效果。
據(jù)此,我還實(shí)現(xiàn)了RichEdit控件背景繪制AVI動(dòng)畫(huà)效果。

65. MFC程序中如何創(chuàng)建多級(jí)目錄

復(fù)制代碼 代碼如下:
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. 解決外部符號(hào)錯(cuò)誤:_main,_WinMain@16,__beginthreadex
在創(chuàng)建MFC項(xiàng)目時(shí), 不使用MFC AppWizard向?qū)? 如果沒(méi)有設(shè)置好項(xiàng)目參數(shù), 就會(huì)在編譯時(shí)產(chǎn)生很多連接錯(cuò)誤, 如error LNK2001錯(cuò)誤, 典型的錯(cuò)誤提示有:
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子系統(tǒng)設(shè)置錯(cuò)誤, 提示:
libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Windows項(xiàng)目要使用Windows子系統(tǒng), 而不是Console, 可以這樣設(shè)置:
[Project] --> [Settings] --> 選擇"Link"屬性頁(yè),
在Project Options中將/subsystem:console改成/subsystem:windows

2). Console子系統(tǒng)設(shè)置錯(cuò)誤, 提示:
LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16
控制臺(tái)項(xiàng)目要使用Console子系統(tǒng), 而不是Windows, 設(shè)置:
[Project] --> [Settings] --> 選擇"Link"屬性頁(yè),
在Project Options中將/subsystem:windows改成/subsystem:console

3). 程序入口設(shè)置錯(cuò)誤, 提示:
msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16
通常, MFC項(xiàng)目的程序入口函數(shù)是WinMain, 如果編譯項(xiàng)目的Unicode版本, 程序入口必須改為wWinMainCRTStartup, 所以需要重新設(shè)置程序入口:
[Project] --> [Settings] --> 選擇"C/C++"屬性頁(yè),
在Category中選擇Output,
再在Entry-point symbol中填入wWinMainCRTStartup, 即可

4). 線程運(yùn)行時(shí)庫(kù)設(shè)置錯(cuò)誤, 提示:
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
這是因?yàn)镸FC要使用多線程時(shí)庫(kù), 需要更改設(shè)置:
[Project] --> [Settings] --> 選擇"C/C++"屬性頁(yè),
在Category中選擇Code Generation,
再在Use run-time library中選擇Debug Multithreaded或者multithreaded
其中,
Single-Threaded單線程靜態(tài)鏈接庫(kù)(release版本)
Multithreaded多線程靜態(tài)鏈接庫(kù)(release版本)
multithreaded DLL多線程動(dòng)態(tài)鏈接庫(kù)(release版本)
Debug Single-Threaded單線程靜態(tài)鏈接庫(kù)(debug版本)
Debug Multithreaded多線程靜態(tài)鏈接庫(kù)(debug版本)
Debug Multithreaded DLL多線程動(dòng)態(tài)鏈接庫(kù)(debug版本)
單線程: 不需要多線程調(diào)用時(shí), 多用在DOS環(huán)境下
多線程: 可以并發(fā)運(yùn)行
靜態(tài)庫(kù): 直接將庫(kù)與程序Link, 可以脫離MFC庫(kù)運(yùn)行
動(dòng)態(tài)庫(kù): 需要相應(yīng)的DLL動(dòng)態(tài)庫(kù), 程序才能運(yùn)行
release版本: 正式發(fā)布時(shí)使用
debug版本: 調(diào)試階段使用

67. 創(chuàng)建包含多個(gè)子目錄的目錄

復(fù)制代碼 代碼如下:
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()
復(fù)制代碼 代碼如下:
#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'對(duì)應(yīng)的nPos是0,'h'對(duì)應(yīng)的nPos是7,以此類推。但是:s.ReverseFind('a')和s.Find('a')的結(jié)果是一樣的。
問(wèn)題是:ReverseFind() 和 Find() 有什么區(qū)別呢:
對(duì)于ReverseFind(),查找順序是從后往前,找到后的nPos是按前后順序排列的。
而Find()是從前往后查的,找到后的nPos也是按前后順序排列的。

69. MDI中如何只屏蔽掉子框架的右上角的關(guān)閉按鈕

復(fù)制代碼 代碼如下:
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. 程序如何刪除自己
復(fù)制代碼 代碼如下:
/////////////////////////////////////////////////
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);
}

  這一段程序思路很簡(jiǎn)單:不是不能在運(yùn)行時(shí)直接刪除本身嗎?好,那么程序先復(fù)制(CLONE)一個(gè)自己,用復(fù)制品起動(dòng)另一個(gè)進(jìn)程,然后自己結(jié)束運(yùn)行,則原來(lái)的EXE文件不被系統(tǒng)保護(hù).這時(shí)由新進(jìn)程作為殺手刪除原來(lái)的EXE文件,并且繼續(xù)完成程序其他的功能。

  新進(jìn)程在運(yùn)行結(jié)束后,復(fù)制品被自動(dòng)刪除。這又是值得介紹的一個(gè)把戲了,注意:

// 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標(biāo)志,這個(gè)標(biāo)志是告訴操作系統(tǒng),當(dāng)和這個(gè)文件相關(guān)的所有句柄都被關(guān)閉之后(包括上面這個(gè)CREATEFILE創(chuàng)建的句炳),就把這個(gè)文件刪除。幾乎所有的臨時(shí)文件在創(chuàng)建時(shí),都指明了這個(gè)標(biāo)志。另外要注意的是:在復(fù)制品進(jìn)程對(duì)原始程序操刀之前,應(yīng)該等待原進(jìn)程退出.在這里用的是進(jìn)程同步技術(shù).用HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE,GetCurrentProcessId());得到原進(jìn)程句柄.SYNCHRONICE標(biāo)志在NT下有效,作用是使OpenProcess得到的句柄可以做為同步對(duì)象.復(fù)制品進(jìn)程用WaitForSingleObject函數(shù)進(jìn)行同步,然后一個(gè)DeleteFile,以及進(jìn)行其它銷毀證據(jù)(比如刪目錄)的工作,一切就完事了。
 
  程序是基于CONSOLE的,通過(guò)傳入的參數(shù)確定是原始的進(jìn)程還是復(fù)制品新進(jìn)程,并且得到需要操作的目標(biāo)文件的信息(主要是路徑),復(fù)制品放在系統(tǒng)的TEMP目錄(GetTempPath得到),你也可以隨便找個(gè)你認(rèn)為安全的地方(比如:WINDOWS\SYSTEM32等等)。這里面沒(méi)有甚么深的技術(shù).再看其他的一些實(shí)現(xiàn)刪除自己的例子,比如說(shuō)在進(jìn)程退出前,用fwrite等方法輸出一個(gè).BAT文件,在里面寫(xiě)幾句DEL,然后WINEXEC一下這個(gè)BAT文件即可.玩兒過(guò)DOS的蟲(chóng)蟲(chóng)大多都會(huì)。
 
71. 隱藏標(biāo)題欄和菜單欄

隱藏標(biāo)題欄 ModifyStyle(WS_CAPTION,0)
隱藏菜單欄 SetMenu(NULL)

72. InflateRect

InflateRect這個(gè)函數(shù)用于增大或減小一個(gè)矩形的大小.
如m_graphRect.InflateRect(-70, -30, -30, -50);
將矩形左邊坐標(biāo)加70,上面加30,右邊減30,下面減50。

73. 怎么讓無(wú)模式對(duì)話框顯示在主窗口后面

要解決這個(gè)問(wèn)題的關(guān)鍵在于CDialog的Create并不能建立一個(gè)無(wú)屬主的窗口.必須用另外方式建窗口. 
  
 比如你的對(duì)話框類叫CDlgNoOwner,在CMainFrame中加一個(gè)CDlgNoOwner類的成員變量, 
 彈出這個(gè)對(duì)話框的消息處理函數(shù)為 

復(fù)制代碼 代碼如下:
 void  CMainFrame::OnNoowner()  
 { 
CDlgNoOwner  *m_dlgTest=new  CDlgNoOwner(this); 
 HWND  hwndDlg=::CreateDialog(AfxGetInstanceHandle(),MAKEINTRESOURCE(CDlgNoOwner::IDD),NULL/*owner*/,NULL/*dlgproc*/); 
 //注意此處DLGPROC為NULL,并不要緊,因?yàn)榻酉乱猻ubclass啦 
 m_dlgTest->SubclassWindow  (hwndDlg);//掛接到成員變量! 
 m_dlgTest->ShowWindow  (SW_SHOW); 
 //這時(shí)可以看到一個(gè)"自由"的對(duì)話框彈出,和你的主窗口是平起平坐的. 
 }

  
 當(dāng)然不要忘了在對(duì)話框關(guān)閉時(shí)DestroyWindow()..那都是在對(duì)話框類中的標(biāo)準(zhǔn)處理了.

74. 隱藏窗口(子窗口沒(méi)有焦點(diǎn)時(shí))

在程序啟動(dòng)時(shí)  InitDialog  中使用  SetWindowPos  將窗體設(shè)置到屏幕以外
然后再隱藏

1.在OnInitDialog()函數(shù)里設(shè)置定時(shí)器:(WINDOWS  API里面響應(yīng)消息WM_INITDIALOG) 
  
 SetTimer(1,  1,  NULL); 
  
 2.添加處理WM_TIMER的消息處理函數(shù)OnTimer,添加代碼: 

復(fù)制代碼 代碼如下:
 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:
復(fù)制代碼 代碼如下:
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:
復(fù)制代碼 代碼如下:
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. 如何實(shí)現(xiàn)點(diǎn)擊對(duì)話框外的地方使對(duì)話框到主窗口的后面

只能將桌面做為父窗口

復(fù)制代碼 代碼如下:
pMDlg = new CMDlg;
pMDlg->Create(IDD_M_DIALOG,CWnd::GetDesktopWindow()/* 設(shè)置父窗口 */);
pMDlg->ShowWindow(SW_SHOW);

然后在任務(wù)欄里隱藏對(duì)話框程序
如何讓對(duì)話框應(yīng)用程序在在任務(wù)欄上不出現(xiàn),并且不隱藏窗口。

解決方法:

  把對(duì)話框的擴(kuò)展屬性修改成為WS_EX_TOOLWINDOW。

程序?qū)崿F(xiàn):

  把對(duì)話框的屬性設(shè)置成為toolwindow,然后在需要的地方執(zhí)行本代碼。

復(fù)制代碼 代碼如下:
  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);

 
77. 想在程序一啟動(dòng)時(shí)就自動(dòng)關(guān)閉窗口,不在任務(wù)欄里顯示

用CTRL+W打開(kāi)ClassWizard;
點(diǎn)擊Class Info頁(yè),類名是工程名Dlg,
再在左下方的"Filter"中選擇"Windows";
回到Message Maps頁(yè),就可以看到消息中有WM_WINDOWPOSCHANGING,
加入代碼,如上所示.
這樣運(yùn)行*.EXE,不但看不到主界面,任務(wù)欄也沒(méi)有,就是任務(wù)管理器中的"應(yīng)用程序"中也不列出,那該如何關(guān)閉它?
在任務(wù)管理器的"進(jìn)程"中可以找到它,這是黑客程序常用的方法.
如果需要的話,連"進(jìn)程"中也看不到.這樣要終止它就是問(wèn)題了.

78.修改打印預(yù)覽的ToolBar

為AFX_IDD_PREVIEW_TOOLBAR這個(gè)ID創(chuàng)建一個(gè)DialogBar。則系統(tǒng)就會(huì)用新創(chuàng)建的DialogBar代替系統(tǒng)默認(rèn)的那個(gè)

79. 如何實(shí)現(xiàn)SDI與MDI的轉(zhuǎn)換?

我想將一個(gè)編好的SDI應(yīng)用程序轉(zhuǎn)換為MDI,很明顯要有多處的改變。
你可以這樣做:建立一個(gè)繼承于CMDIChidWnd的類,不防設(shè)為CChldFrm.在CWinApp中作如下變化。

復(fù)制代碼 代碼如下:
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,編譯運(yùn)行后你就會(huì)發(fā)現(xiàn)程序已經(jīng)從SDI變換到MDI。
注意:在CMainFram中必須將構(gòu)造函數(shù)從private改為public.否則會(huì)出錯(cuò)。

80. CDC中的豎排文本?

在OnDraw成員函數(shù)中我想讓文本豎直對(duì)齊,但CDC類似乎不支持該處理
方法一:如果你的豎直對(duì)齊是指旋轉(zhuǎn)文本的話,下面的代碼會(huì)對(duì)你有幫助:該代碼檢查一個(gè)Check box控制,查看文本是否需要旋轉(zhuǎn).

復(fù)制代碼 代碼如下:
// 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中選擇了不同的字體,你應(yīng)該自己設(shè)定LOGFONT的lfEscapement成員.將初始化后的lfEscapement值傳到CFontDialog中.
方法二:還有一段代碼可參考:
復(fù)制代碼 代碼如下:
LOGFONT LocalLogFont;
strcpy(LocalLogFont.lfFaceName, TypeFace);
LocalLogFont.lfWeight = fWeight;
LocalLogFont.lfEscapement = Orient;
LocalLogFont.lfOrientation = Orient;
if (MyFont.CreateFontIndirect(&LocalLogFont))
  {
  cMyOldFont = cdc->SelectObject(&MyFont);
  }

81. 如何用鍵盤滾動(dòng)分割的視口?
我的問(wèn)題是當(dāng)我用鼠標(biāo)滾動(dòng)分割窗口時(shí),視口滾動(dòng)都很正常,但用鍵盤時(shí),卻什么也沒(méi)有發(fā)生.
在你的視圖繼承類中加入如下兩個(gè)函數(shù),假定該類為CScrollerView:
復(fù)制代碼 代碼如下:
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. 如何改變默認(rèn)的光標(biāo)形狀?
我試著將光標(biāo)改變?yōu)槠渌男螤詈皖伾?但卻沒(méi)有變化.
在對(duì)話框/窗口/你需要的地方加上對(duì)WM_SETCURSOR消息的處理.
復(fù)制代碼 代碼如下:
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);
}

你沒(méi)有成功的原因是因?yàn)榇翱陬惞鈽?biāo)風(fēng)格不能為NULL.

83. 如何選擇CTreeCtrl中的節(jié)點(diǎn)文本進(jìn)行編輯?

在向CTreeCtrl中加入一項(xiàng)后,有什么方法可以編輯該節(jié)點(diǎn)的文本呢?
首先設(shè)置你的CcompTreeCtrl具有TVS_EDITLABELS屬性.在設(shè)計(jì)時(shí)用控件屬性來(lái)設(shè)置在運(yùn)行時(shí)用GetStyle()/SetStyle()成員函數(shù)來(lái)設(shè)置.然后請(qǐng)看下述代碼:

復(fù)制代碼 代碼如下:
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中選擇變化時(shí)如何獲得通知?

我在Report View中使用了一個(gè)CListCtrl(自繪制類型),我想知道什么時(shí)候選擇項(xiàng)發(fā)生了改變.
在選擇項(xiàng)變化時(shí),可以使用按鈕有效或失效,按如下操作:
 加入LVN_ITEMCHANGED消息處理.

復(fù)制代碼 代碼如下:
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控件時(shí)碰到了麻煩,我想創(chuàng)建一個(gè)ListView,來(lái)依據(jù)Tree控件的選擇同時(shí)在ListView和ReportView中顯示列表的信息.以下是相關(guān)的代碼:
復(fù)制代碼 代碼如下:
// Set full line select
ListView_SetExtendedListViewStyle(m_plstCustomers->GetSafeHwnd(),
LVS_EX_FULLROWSELECT);

按如下方法處理:
復(fù)制代碼 代碼如下:
// -------------------- 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子框架最大化時(shí)的大小?

用ptMaxTrackSize代替prMaxSize,如下所示:

復(fù)制代碼 代碼如下:
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. 怎樣實(shí)現(xiàn)3D效果?

在對(duì)話框中怎樣實(shí)現(xiàn)Edit和Listboxes控件的3D效果?(環(huán)境95/NT VC5.0)

1). 使用帶WS_EX_CLIENTEDGE標(biāo)志的::CreateWindowEx來(lái)替換::CreateWindow 或者用CWnd::CreateEx替換CWnd::Create.

2).在建立控件之后,調(diào)用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):

復(fù)制代碼 代碼如下:
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:
復(fù)制代碼 代碼如下:
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. 動(dòng)態(tài)修改對(duì)話框的大小

問(wèn)題提出:

  關(guān)于如何動(dòng)態(tài)改變對(duì)話框的大小,我做了個(gè)Demo,大家看看.

程序?qū)崿F(xiàn):

復(fù)制代碼 代碼如下:
   //本函數(shù)使用方法:
   //第一個(gè)參數(shù):如果是TRUE表示顯示擴(kuò)展的對(duì)話框,如果是FALSE,表示縮小對(duì)話框。
   //第二個(gè)參數(shù):表示本對(duì)話框的HWND,
   //第三個(gè)參數(shù):表示縮小后大小的控件的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()調(diào)用模態(tài)對(duì)話框,總是顯示在正中,我重載了它,并添加了MoveWindow(),可是其m_hWnd是一串零,調(diào)用失敗。請(qǐng)問(wèn)有何方法可使調(diào)用的模態(tài)對(duì)話框顯示于自定義位置?多謝

  我不清楚你把MoveWindow()加在什么地方了,正確的方法是在OnInitDialog中添加MoveWindow,如:

復(fù)制代碼 代碼如下:
MoveWindow(0, 1, 300, 200);

  需要注意的是前兩個(gè)參數(shù)不能都為0。如果你確實(shí)希望把窗口放在(0, 0)處,可以在對(duì)話框設(shè)計(jì)窗口的屬性中選中Absolute Align,然后再加入
復(fù)制代碼 代碼如下:
MoveWindow(0, 0, 300, 200);

  為什么會(huì)是這樣?你看了MFC的源程序就會(huì)明白。原來(lái)MFC在調(diào)用你的OnInitDialog之后,會(huì)調(diào)用CDialog::CheckAutoCenter()(在dlgcore.cpp中)檢查是否需要將窗口居中,你看了這個(gè)函數(shù)后就明白為什么需要上面那么做了。

希望本文所述對(duì)大家的MFC程序設(shè)計(jì)有所幫助。

相關(guān)文章

最新評(píng)論