• VC中常见的108个问题


    (1) 怎样通过代码获得应用程序主窗体的 指针?


    主窗体的 指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现。


    AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED)
    //使程序最大化.

    (2) 确定应用程序的路径
    Use GetModuleFileName 获得应用程序的路径,然后去掉可运行文件名称。
    Example:
    TCHAR
    exeFullPath[MAX_PATH] // MAX_PATH在API中定义了吧。好象是
    128
    GetModuleFileName(NULL,exeFullPath,MAX_PATH)

    (3) 怎样在程序中获得其它程序的 图标?
    两种方法:
    (1) SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的 handle,
    (2) SDK函数 SHGetFileInfo 获得有关文件的非常多信息,如大小图标,属性, 类型等.
    Example(1):
    在程序窗体左上角显示 NotePad图标.
    void CSampleView:
    OnDraw(CDC * pDC)
    {
    if( :: SHGetFileInfo(_T("c:\pwin95\notepad.exe"),0,
    &stFileInfo,sizeof(stFileInfo),SHGFI_ICON))
    {
    pDC ->DrawIcon(10,10,stFileInfo.hIcon)
    }
    }
    Example(2):相同功能,Use ExtractIcon Function
    void CSampleView:: OnDraw(CDC *pDC)
    {
    HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T
    ("NotePad.exe"),0)
    if (hIcon &&hIcon!=(HICON)-1)
    pDC->DrawIcon(10,10,hIcon)
    }
        说明: 获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到, 假设是调用 win95下的画笔,应该用訪问注冊表的方法获得其路径。要作成一个比較考究的程序。考虑应该全面点. 
     

    (4) 获得各种文件夹信息
    Windows文件夹: Use "GetWindowsDirectory"
    Windows下的system文件夹: Use "GetSystemDirectory"
    temp文件夹: Use "GetTempPath"
    当前文件夹: Use "GetCurrentDirectory"

    请注意前两个函数的第一个參数为文件夹变量名,后一个为缓冲区后两个相反.


    (5) 怎样自己定义消息
    1) 手工定义消息,能够这么写
    #define WM_MY_MESSAGE(WM_USER+100),
    MS 推荐的至少是 WM_USER+100

    (2)写消息处理函数,用
    WPARAM,LPARAM返回LRESULT.
    LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)

    {
    temp文件夹: Use "GetTempPath"
    //增加你的处理函数 irectory"
    }
    (6) 怎样改变窗体的图标?
    向窗体发送 WM_SECTION消息。
    Example:
    HICON hIcon=AfxGetApp() ->LoadIcon(IDI_ICON)
    ASSERT(hIcon)
    AfxGetMainWnd() ->SendMessage(WM_SECTION,TRUE,(LPARAM)hIcon)

    (7) 怎样改变窗体的缺省风格?


    重载 CWnd:: PreCreateWindow 并改动CREATESTRUCT结构来指定窗体风格和其它创建信息.
    Example: Delete "Max" Button and Set Original
    Window's Position and Size

    BOOL CMainFrame:: PreCreateWindow
    (CREATESTRUCT &cs)
    {
    cs.style &=~WS_MAXINIZEMOX

    cs.x=cs.y=0
    cs.cx=GetSystemMetrics(SM_CXSCREEN/2)
    cs.cy=GetSystemMetrics(SM_CYSCREEN/2)

    return CMDIFramewnd ::PreCreateWindow(cs)
    }
    (8) 怎样将窗体居中显示?
    Call Function CWnd::
    Center Windows

    Example(1):
    Center Window( ) //Relative to it's parent
    // Relative
    to Screen
    Example(2):
    Center Window(CWnd:: GetDesktopWindow( ))
    //Relative to
    Application's MainWindow
    AfxGetMainWnd( ) ->
    Center Window( )

    (9) 怎样让窗体和 MDI窗体一启动就最大化和最小化?
    先说窗体。


    在 InitStance 函数中设定 m_nCmdShow的取值.
    m_nCmdShow=SW_SHOWMAXMIZED //最大化
    m_nCmdShow=SW_SHOWMINMIZED //最小化
    m_nCmdShow=SW_SHOWNORMAL //正常方式

    MDI窗体:
    假设是创建新的应用程序,能够用MFC AppWizard 的Advanced button并在MDI子窗体风格组中检測最大化或最小化还能够重载 MDI Window 的PreCreateWindow函数,设置WS_MAXMIZE or WS_MINMIZE

    假设从 CMDIChildWnd派生,调用 OnInitialUpdate函数中的 CWnd::Show Window来指定 MDI Child Window的风格。
    (10) 怎样限制窗体的大小?
    也就是 FixedDialog形式。

    Windows发送 WM_GETMAXMININFO消息来跟踪, 响应它,在 OnGetMAXMININFO 中写代码:
    (11) 怎样使窗体不可见?
    非常easy,用SW_HIDE 隐藏窗体,能够结合 FindWindow,ShowWindow控制.
    (12) 怎样创建一个字回绕的CEditView
    重载CWnd : : PreCreateWindow和改动CREATESTRUCT结构,关闭CEditView对象的ES_AUTOHSCROLL和WS_HSCROLL风格位。 因为CEditView : : PreCreateWindow显示设置cs. style,调用基类函数后要改动cs . style。



    BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&cs)
    {
    //First call basse class function .
    BOOL bResutl =CEditView : : PreCreateWindow (cs)

    // Now specify the new window style .
    cs.style &= ~ (ES_AUTOHSCROLL |WS_HSCROLL)
    return bResult
    }

    (13) 怎样使程序保持极小状态?
    这么办: 在恢复程序窗口大小时,Windows会发送WM_QUERY-OPEN消息,用 ClassWizard设置成员函数
    OnQueryOpen() ,add following code:

    Bool CMainFrame:: OnQueryOpen( )
    {
    Return false
    }
    (14) 移动窗体
    调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗体有关(顶层窗体与屏幕有关)。

    调用CWnd : : MoveWindow时必需要指定窗体的大小。
    //Move window to positoin 100 , 100 of its parent window .
    SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER)
    (15) 通用控件的显示窗体
    MFC提供了几个CView派生的视窗类, 封装了通用控件的功能。但仍然使用工作框文档显示窗体体系结构:CEditView封装了编辑控件。CTreeView保持了树列表控件。CListView封装了列表显示窗体控件,CRichEditView能够处理多种编辑控件。
    (16) 重置窗体的大小
    调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可调用CWnd : : MoveWindow 但必须指定窗体的位置。


    // Get the size of the window .
    Crect reWindow
    GetWindowRect (reWindow )

    //Make the window twice as wide and twice as tall .
    SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,

    reWindow . Height () * 2,
    SWP_NOMOVE |SWP_NOZORDER )
    (17) 怎样单击除了窗体标题栏以外的区域使窗体移动
    当窗体须要确定鼠标位置时Windows向窗体发送WM_NCHITTEST信息,能够处理该信息使Windows觉得鼠标在窗体标题上。

    对于对话框和基于对话的应用程序,能够使用ClassWizard处理该信息并调用基类函数, 假设函数返回HTCLIENT 则表明鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。
    UINT CSampleDialog : : OnNcHitTest (Cpoint point )
    {
    UINT nHitTest =Cdialog: : OnNcHitTest (point )
    return (nHitTest = =HTCLIENT)?

    HTCAPTION : nHitTest
    }

    上述技术有两点不利之处。
    其一是在窗体的客户区域双击时。窗体将极大;
    其二, 它不适合包括几个视窗的主框窗体。
    另一种方法,当用户按下鼠标左键使主框窗体觉得鼠标在其窗体标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗体发送一个WM_NCLBUTTONDOWN信息和一个单击測试HTCAPTION。
    void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point
    )
    {
    CView : : OnLButtonDow (nFlags , pont )

    //Fool frame window into thinking somene clicked
    on
    its caption bar .
    GetParentFrame ( ) —> PostMessage (
    WM_NCLBUTTONDOWN ,
    HTCAPTION , MAKELPARAM (poitn .x , point .y) )

    }
    该技术也适用于对话框和基于对的应用程序,仅仅是不必调用
    CWnd: :GetParentFrame 。
    void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )
    {
    Cdialog : : OnLButtonDow (nFlags, goint )
    //Fool dialog into thinking simeone clicked on its
    caption bar .
    PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x
    , point. y
    ) )
    }
    (18) 怎样改变视窗的背景颜色
    Windows向窗体发送一个WM_ERASEBKGND消息通知该窗体擦除背景,能够使用ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以防止Windows擦除窗体。
    //Paint area that needs to be erased.
    BOOL CSampleView : : OnEraseBkgnd (CDC* pDC)
    {
    // Create a pruple brush.
    CBrush Brush (RGB (128 , 0 , 128) )

    // Select the brush into the device context .
    CBrush* pOldBrush = pDC—>SelcetObject (&brush)

    // Get the area that needs to be erased .
    CRect reClip
    pDC—>GetCilpBox (&rcClip)
    //Paint the area.
    pDC—> PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY )

    //Unselect brush out of device context .
    pDC—>SelectObject (pOldBrush )

    // Return nonzero to half fruther processing .
    return TRUE
    }
    (19) 怎样改变窗体标题
    调用CWnd : : SetWindowText能够改变不论什么窗体(包含控件)的标题。
    //Set title for application's main frame window .
    AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") )

    //Set title for View's MDI child frame window .
    GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title")
    )

    //Set title for dialog's push button control.
    GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") )
    假设须要常常改动窗体的标题(注:控件也是窗体),应该考虑使用半文档化的函数AfxSetWindowText。

    该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在联机帮助中找不到它。它在AFXPRIV.H中半文档化, 在以后发行的MFC中将文档化。


    AfxSetWindowText的实现例如以下:
    voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )
    {
    itn nNewLen= Istrlen (Ipaznew)
    TCHAR szOld [256]
    //fast check to see if text really changes (reduces
    flash in the
    controls )
    if (nNewLen >_contof (szOld)
    || : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen
    || Istrcmp (szOld , IpszNew)! = 0
    {
    //change it
    : : SetWindowText(hWndCtrl , IpszNew )
    }
    }
    (20) 怎样防止主框窗体在其说明中显示活动的文档名
    创建主框窗体和MDI子窗体进通常具有FWS_ADDTOTITLE风格位,假设不希望在说明中自己主动加入文档名, 必须禁止该风格位。 能够使用ClassWizard重置
    CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。


    BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)
    {
    //Turn off FWS_ADDTOTITLE in main frame .
    cs.styel & = ~FWS_ADDTOTITLE  
    return CMDIFrameWnd : : PreCreateWindow (cs )
    }
    关闭MDI子窗体的FWS _ADDTOTITLE风格将创建一个具有空标题的窗体,能够调用CWnd: : SetWindowText来设置标题。

    记住自己设置标题时要遵循接口风格指南。


    (21) 怎样获取有关窗体正在处理的当前消息的信息
    调用CWnd: : GetCurrentMessage能够获取一个MSG指针。比如,能够使用ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage来确定所选中的菜单项。
    viod CMainFrame : : OnCommmonMenuHandler ( )
    {
    //Display selected menu item in debug window .
    TRACE ("Menu item %u was selected . " ,
    (22) 怎样在代码中获取工具条和状态条的指针
    缺省时, 工作框创建状态条和工具条时将它们作为主框窗体的子窗体。状态条有一个AFX_IDW_STATUS_BAR标识符。工具条有一个AFX_IDW_TOOLBAR标识符。下例说明了怎样通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗体的指针:
    //Get pointer to status bar .
    CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
    —> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

    //Get pointer to toolbar .
    CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
    —> GetDescendantWindow(AFX_IDW_TOOLBAR)
    (23) 怎样使能和禁止工具条的工具提示
    假设设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,须要设置或者清除该风格位。

    下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完毕此功能的成员函数:
    void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )
    {
    ASSERT_VALID (m_wndToolBar)

    DWORD dwStyle = m _wndToolBar.GetBarStyle ( )

    if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS

    else
    dwStyle & = ~CBRS_TOOLTIPS

    m_wndToolBar.SetBarStyle (dwStyle )
    }
    (24) 怎样创建一个不规则形状的窗体
    能够使用新的SDK函数SetWindowRgn。

    该函数将绘画和鼠标消息限定在窗体的一个指定的区域。实际上使窗体成为指定的不规则形状。

    使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。
    给对话类添加一个CRgn数据成员,以后要使用该数据成员建立窗体区域。


    Class CRoundDlg : public CDialog
    {

    private :
    Crgn m_rgn : // window region

    }
    改动OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗体:
    BOOL CRoundDlg : : OnInitDialog ( )
    {
    CDialog : : OnInitDialog ( )

    //Get size of dialog .
    CRect rcDialog
    GetClientRect (rcDialog )

    // Create region and assign to window .
    m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) )
    SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE )

    return TRUE
    }

    通过建立区域和调用SetWindowRgn。已经建立一个不规则形状的窗体,以下的样例程序是改动OnPaint函数使窗体形状看起来象一个球形体。
    voik CRoundDlg : : OnPaint ( )
    {
    CPaintDC de (this) // device context for painting
    .
    //draw ellipse with out any border
    dc. SelecStockObject (NULL_PEN)
    //get the RGB colour components of the sphere color
    COLORREF color= RGB( 0 , 0 , 255)
    BYTE byRed =GetRValue (color)
    BYTE byGreen = GetGValue (color)
    BYTE byBlue = GetBValue (color)

    // get the size of the view window
    Crect rect
    GetClientRect (rect)

    // get minimun number of units
    int nUnits =min (rect.right , rect.bottom )

    //calculate he horiaontal and vertical step size
    float fltStepHorz = (float) rect.right /nUnits
    float fltStepVert = (float) rect.bottom /nUnits


    int nEllipse = nUnits/3 // calculate how many to
    draw
    int nIndex
    // current ellipse that is being draw

    CBrush brush
    // bursh used for ellipse fill color
    CBrush *pBrushOld // previous
    brush that was selected into dc
    //draw ellipse , gradually moving towards upper-right
    corner
    for (nIndex = 0 nIndes < + nEllipse nIndes++)
    {
    //creat solid brush
    brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ).
    ( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)
    /nEllipse ) ) )

    //select brush into dc
    pBrushOld= dc .SelectObject (&brhsh)

    //draw ellipse
    dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex ,
    rect. right -( (int) fltStepHorz * nIndex )+ 1,
    rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1)

    //delete the brush
    brush.DelecteObject ( )
    }
    }

    最后,处理WM_NCHITTEST消息,使当击打窗体的不论什么位置时能移动窗体。
    UINT CRoundDlg : : OnNchitTest (Cpoint point )
    {
    //Let user move window by clickign anywhere on thewindow .
    UINT nHitTest = CDialog : : OnNcHitTest (point)
    rerurn (nHitTest = = HTCLIENT)?

    HTCAPTION: nHitTest

    }
    (25) 怎样获取应用程序的 实例句柄?


    应用程序的实例句柄保存在CWinApp m_hInstance 中,能够这么调用AfxGetInstancdHandle获得句柄.
    Example: HANDLE hInstance=AfxGetInstanceHandle()
    (26) 怎样编程结束应用程序?
    这是个非常easy又是编程中常常要遇到的问题.
    向窗体发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.同意对用户提示是否保存改动过的数据.
    Example: AfxGetMainWindow()->SendMessage(WM_CLOSE)

    还能够创建一个自己定义的函数 Terminate Window
    void Terminate Window(LPCSTR pCaption)
    {
    CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption)

    if (pWnd)

    pWnd ->SendMessage(WM_CLOSE)
    }

        说明: FindWindow函数不是提倡的做法,由于它无法处理标题栏自己主动改变,比方我们要检測 Notepad是不是已执行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了。能够通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发者指南"一书有比較具体的介绍,这里就不再多说乐。
    (27) 怎样创建和使用无模式对话框
    MFC将模式和无模式对话封装在同一个类中,可是使用无模式对话须要几个对话须要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。

    模式和无模式对话的中止是不一样的:模式对话通过调用CDialog : : EndDialog 来中止。无模式对话则是调用CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以须要调用DestroyWindow并重置无模式对话的函数。
    void CSampleDialog : : OnOK ( )
    {
    // Retrieve and validate dialog data .
    if (! UpdateData (TRUE) )
    {
    // the UpdateData rountine
    will set focus to correct item TRACEO (" UpdateData failed during dialog termination . ")
    return
    }

    //Call DestroyWindow instead of EndDialog .
    DestroyWindow ( )
    }

    void CSampleDialog : : OnCancel ( )
    {
    //Call DestroyWindow instead of EndDialog .
    DestroyWindow ( )
    }

    其次。须要正确删除表示对话的C++对象。对于模式对来说,这非常easy,须要创建函数返回后就可以删除C++对象;无模式对话不是同步的,创建函数调用后马上返回,因而用户不知道何时删除C++对象。

    撤销窗体时工作框调用CWnd : : PostNcDestroy,能够重置该函数并运行清除操作,诸如删除this指针。


    void CSampleDialog : : PostNcDestroy ( )
    {
    // Declete the C++ object that represents this dialog.
    delete this

    最后。要创建无模式对话。

    能够调用CDialog : : DoModal创建一个模式对放。要创建一个无模式对话则要调用CDialog: : Create。以下的样例说明 了应用程序是怎样创建无模式对话的: 象;无模式对话不是同步的。创建函数调用后马上返回,
    void CMainFrame : : OnSampleDialog ( )
    {
    //Allocate a modeless dialog object .
    CSampleDilog * pDialog =new CSampleDialog
    ASSERT_VALID (pDialog) Destroy ( )

    //Create the modeless dialog . represents this dialog.
    BOOL bResult = pDialog —> Creste (IDD_IDALOG)
    ASSERT (bResult )
    }


    (28) 怎样防止主框窗体在其说明中显示活动的文档名
    创建主框窗体和MDI子窗体进通常具有FWS_ADDTOTITLE风格位,假设不希望在说明中自己主动加入文档名, 必须禁止该风格位, 能够使用ClassWizard重置
    CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。


    BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)
    {
    //Turn off FWS_ADDTOTITLE in main frame .
    cs.styel & = ~FWS_ADDTOTITLE  
    return CMDIFrameWnd : : PreCreateWindow (cs )
    }
    关闭MDI子窗体的FWS _ADDTOTITLE风格将创建一个具有空标题的窗体,能够调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。


    (29) 怎样在代码中获取工具条和状态条的指针
    缺省时。 工作框创建状态条和工具条时将它们作为主框窗体的子窗体,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了怎样通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗体的指针:
    //Get pointer to status bar .
    CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
    —> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

    //Get pointer to toolbar .
    CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
    —> GetDescendantWindow(AFX_IDW_TOOLBAR)

    (30) 如何载入其它的应用程序?
    三个SDK函数 winexec, shellexecute,createprocess能够使用。
    WinExec最简单。两个參数,前一个指定路径。后一个指定显示方式.后一个參数值得说一下,比方泥用 SW_SHOWMAXMIZED方式去载入一个无最大化button的程序。就是Neterm,calc等等。就不会出现正常的窗口,可是已经被加到任务列表里了。

    ShellExecute较 WinExex灵活一点,能够指定工作文件夹,以下的Example就是直接打开 c: emp1.txt,而不用载入与 txt文件关联的应用程序,非常多安装程序完毕后都会打开一个窗体,来显示Readme or Faq,我猜就是这么作的啦.

    ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c:\temp"),SW_SHOWMAXMIZED)

    CreateProcess最复杂。一共同拥有十个參数,只是大部分都能够用NULL取代,它能够指定进程的安全属性,继承信息。类的优先级等等.来看个非常easy的Example:
    STARTUPINFO stinfo
    //启动窗体的信息
    PROCESSINFO procinfo //进程的信息

    CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,
    NORMAL_PRIORITY_

    CLASS,NULL,NULL, &stinfo,&procinfo)

    (31) 怎样在代码中获取工具条和状态条的指针
    缺省时。 工作框创建状态条和工具条时将它们作为主框窗体的子窗体。状态条有一个AFX_IDW_STATUS_BAR标识符。工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了怎样通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗体的指针:
    //Get pointer to status bar .
    CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
    —> GetDescendantWindow(AFX_IDW_STUTUS_BAR)
    (32) 怎样使能和禁止工具条的工具提示
    假设设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示。须要设置或者清除该风格位。

    下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完毕此功能的成员函数:
    void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )
    {
    ASSERT_VALID (m_wndToolBar)

    DWORD dwStyle = m _wndToolBar.GetBarStyle ( )

    if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS

    else
    dwStyle & = ~CBRS_TOOLTIPS

    m_wndToolBar.SetBarStyle (dwStyle )
    }

    //Get pointer to toolbar .
    CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
    —> GetDescendantWindow(AFX_IDW_TOOLBAR)
    (33) 怎样设置工具条标题
    工具条是一个窗体。所以能够在调用CWnd : : SetWindowText来设置标题,样例例如以下:
    int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct )
    {

    // Set the caption of the toolbar .
    m_wndToolBar.SetWindowText (_T "Standdard")
    (34) 怎样使窗体始终在最前方?
    BringWindowToTop(Handle)
    SetWindowPos函数,指定窗体的 最顶风格,用WS_EX_TOPMOST扩展窗体的风格

    Example:
    void ToggleTopMost(
    CWnd *pWnd)
    {
    ASSERT_VALID(pWnd)

    pWnd ->SetWindowPos(pWnd-> GetStyle( ) &WS_EX_TOPMOST)?



    &wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE)
    }
    (35) 怎样在对话框中显示一个位图
    这要归功于Win 32先进的静态控件和Microsoft的资源编辑器,在对话框中显示位图是非常easy的。 仅仅需将图形控件拖到对话中并选择适当属性就可以。用户也能够显示图标、位图以及增强型元文件。


    (36) 怎样改变对话或窗口视窗的背景颜色
    调用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
    )
    }
    (37) 怎样获取一个对话控件的指针
    有两种方法。其一。调用CWnd: : GetDlgItem,获取一个CWnd*指针调用成员函数。下例调用GetDlgItem,将返回值传给一个CSpinButtonCtrl*以便调用CSpinButtonCtrl : : SetPos 函数:
    BOOL CSampleDialog : : OnInitDialog ( )
    {
    CDialog : : OnInitDialog ( )

    //Get pointer to spin button .
    CSpinButtonCtrl * pSpin - ( CSpinButtonCtrl *) GetDlgItem(IDC_SPIN)
    ASSERT _ VALID (pSpin)
    //Set spin button's default position .
    pSpin —> SetPos (10)

    return TRUE
    }

    其二。 能够使用ClassWizard将控件和成员变量联系起来。在ClassWizard中简单地选择Member Variables标签,然后选择Add Variable …button。假设在对话资源编辑器中。按下Ctrl键并双击控件就可以转到Add Member Variable对话。



    (38) 怎样禁止和使能控件
    控件也是窗体,所以能够调用CWnd : : EnableWindow使能和禁止控件。
    //Disable button controls .
    m_wndOK.EnableWindow (FALSE )
    m_wndApply.EnableWindow (FALSE )

    (39) 怎样改变控件的字体
    因为控件是也是窗体。用户能够调用CWnd: : SetFont指定新字体。该函数用一个Cfont指针,要保证在控件撤消之前不能撤消字体对象。下例将下压button的字体改为8点Arial字体:
    //Declare font object in class declaration (.H file ).
    private : Cfont m_font
    // Set font in class implementation (.Cpp file ). Note m_wndButton is a
    //member variable added by ClassWizard.DDX routines hook the member
    //variable to a dialog button contrlo.
    BOOL CSampleDialog : : OnInitDialog ( )
    {

    //Create an 8-point Arial font
    m_font . CreateFont (MulDiv (8 , -pDC
    —> GetDeviceCaps(LOGPIXELSY) ,72). 0 , 0 , 0 , FW_NORMAL , 0 , 0,0, ANSI_CHARSER, OUT_STROKE_PRECIS ,

    CLIP_STROKE _PRECIS , DRAFT _QUALITY
    VARIABLE_PITCH |FF_SWISS, _T("Arial") )

    //Set font for push button .
    m_wndButton . SetFont (&m _font )


    }
    (40) 怎样在OLE控件中使用OLE_COLOR数据类型
    诸如COleControl : : GetFortColor和COleControl : : GetBackColor等函数返回OLE _COLOR数据类型的颜色。而GDI对象诸如笔和刷子使用的是COLORREF数据类型。调用COleControl : : TranslateColor能够非常easy地将OLE_COLOR类型改为COLORREF类型。下例创建了一个当前背景颜色的刷子:

    void CSampleControl : : OnDraw (CDC* pdc
    const Crect& rcBounds , const Crect& rcInvalid
    )
    {
    //Create a brush of the cuttent background color.
    CBrush brushBack (TranslateColor (GetBackColor () ) )

    //Paint the background using the current backgroundcolor .
    pdc—> FilllRect (rcBounds , &brushBack)

    //other drawign commands


    }
     
     
    (41) 在不使用通用文件打开对话的情况下怎样显示一个文件列表
    调用CWnd: : DlgDirList或者CWnd: : DlgDirListComboBox,Windows 将自己主动地向列表框或组合框填充可用的驱动器名或者指定文件夹中的文件,下例将Windows文件夹中的文件填充在组合框中:
    BOOL CSampleDig : : OnInitDialog ( )
    {
    CDialog : : OnInitDialog ( )
    TCHAR szPath [MAX_PATH] = {"c:\windows"}
    int nReslt = DlgDirListComboBox (szPath, IDC_COMBO , IDC_CURIDIR, DDL_READWRITE |DDL_READONLY|DDL_HIDDEN| DDL_SYSTEM|DDL_ARCHIVE)
    return TRUE
    }
    (42) 为什么旋转button控件看起来倒转
    须要调用CSpinCtrl : : SetRange 设置旋转button控件的范围,旋转button控件的缺省上限为0,缺省下限为100。这意味着添加时旋转按控件的值由100变为0。下例将旋转button控件的范围设置为0到100:
    BOOL CAboutDlg : : OnInitDialog ( )
    {
    CDialog : : OnInitDialog ( )

    //set the lower and upper limit of the spin button
    m_wndSpin . SetRange ( 0 ,100 )

    return TRUE
    }

    Visual C++ 4.0 Print对话中的Copise旋转button控件也有相同的问题:按下Upbutton时拷贝的数目降低,而按下Down button时拷贝的数目添加。
    (43) 为什么旋转button控件不能自己主动地更新它以下的编辑控件
    假设使用旋转button的autu buddy特性, 则必须保证在对话的标记顺序中buddy窗体优先于旋转button控件。从Layout菜单中选择Tab Order菜单项(或者按下Crtl+D)能够设置对话的标签顺序。
    (44) 怎样用位图显示下压button
    Windows 95button有几处新的创建风格。尤其是BS_BITMAP和BS_ICON,要想具有位图button。创建button和调用CButton : : SetBitmap或CButton : : SetIcon时要指定BS_BITMAP或BS_ICON风格。

    首先,设置button的图标属性。然后,当对话初始化时调用CButton: : SetIcon。

    注意:下例用图标取代位图,使用位图时要小心。由于不知道背景全部的颜色——并不是每一个人都使用浅灰色。

    BOOL CSampleDlg : : OnInitDialog ( )
    {
    CDialog : : OnInitDialog ( )

    //set the images for the push buttons .
    BOOL CSampleDlg : : OnInitDialog ( )
    {
    CDialog : : OnInitDialog ( )

    //set the images for the push buttons .
    m_wndButton1.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION1))
    m_wndButton2.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION2))
    m_wndButton3.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION3))

    return TRUE
    }

    (45) 怎样一个创建三态下压button
    能够使用新的BS_PUSHBUTTON 风格位和检測框以及button来创建一个三态下压button。

    这非常easy,仅仅需将检測框和button拖拉到对话中并指定属性Push—like就可以。

    不用不论什么附加程序就能够成为三态下压button。
    (46) 怎样动态创建控件
    分配一个控件对象的实例并调用其Create成员函数。开发人员最easy忽略两件事:忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压button控件:
    //In class declaration (.H file ).
    private : CButton* m _pButton

    //In class implementation (.cpp file ) .
    m_pButton =new CButton
    ASSERT_VALID (m_pButton)
    m_pButton —>Create (_T ("Button Title ") , WS_CHILD |WS_VISIBLE |BS_PUSHBUTTON. Crect ( 0, 0, 100 , 24) , this , IDC _MYBUTTON )
    (47) 怎样限制编辑框中的准许字符
    假设用户在编辑控件中仅仅同意接收数字,能够使用一个标准的编辑控件并指定新的创建标志ES_NUMBERS,它是Windows 95新添加的标志,该标志限制 编辑控件仅仅按收数字字符。假设用户须要复杂的编辑控件,能够使用Microsoft 的屏蔽编辑控件。它是一个非常实用的OLE定制控件。


    假设希望不使用OLE 定制控件自己处理字符,能够派生一个CEdit类并处理WM_CHAR消息。然后从编辑控件中过滤出特定的字符。首先。使用ClassWizard建立一个 CEdit的派生类,其次。在对话类中指定一个成员变量将编辑控件分类在OnInitdialog 中调用CWnd: : SubclassDlgItem .

    //In your dialog class declaration (.H file )
    private : CMyEdit m_wndEdit // Instance of your new edit control .

    //In you dialog class implementation (.CPP file )
    BOOL CSampleDialog : : OnInitDialog ( )
    {


    //Subclass the edit lontrod .
    m_wndEdit .SubclassDlgItem (IDC_EDIT,this)


    }

    使用ClassWizard处理WM_CHAR消息,计算nChar參量并决定所运行的操作。用户能够确定是否改动、传送字符。下例说明了怎样显示字母字符,假设字符是字母字符,则调用CWnd OnChar,否则不调用OnChar.
    //Only display alphabetic dharacters .
    void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UITN nFlags )
    {
    //Determine if nChar is an alphabetic character.
    if (: : IsCharAlpha ( ( TCHAR) nChar ) )
    CEdit : : OnChar (nChar, nRepCnt , nFlags )
    }

    假设要改动字符,则不能只简单地用改动过的nChar调用CEdit: : OnChar,然后CEdit: : OnChar调用CWnd: : Default获取原来的wParam 和lParam 的值,这样是不行的。要改动一个字符,须要首先改动nChar,然后用改动过的nChar调用CWnd: : DefWindowProc。

    下例说明了怎样将字符转变为大写:
    //Make all characters uppercase
    void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UINT nFlags )
    {
    //Make sure character is uppercase .
    if (: : IsCharAlpha ( .( TCHAR) nChar)
    nChar=: : CharUpper(nChar )

    //Bypass default OnChar processing and directly call
    //default window proc.
    DefWindProc (WM_CHAR, nChar , MAKELPARAM (nRepCnt, nFlags ))
    }
    (48) 怎样改变控件的颜色
    有两种方法。

    其一,能够在父类中指定控件的颜色,或者利用MFC4.0新的消息反射在控件类中指定颜色。

    当控件须要又一次着色时,工作框调用父窗体(一般是对话框)的CWnd: : OnCrtlColor,能够在父窗体类中重置该函数并指定控件的新的绘画属性。比如。下述代码将对话中的全部编辑控件文本颜色改为红色:
    HBRUSH CAboutDig : : OnCtlColor (CDC * pDCM , CWnd * pWnd , UINT nCtlColor)

    {
    HBRUSH hbr = CDialog : : OnCtlColor (pDC, pWnd , nCtlColor )

    //Draw red text for all edit controls .
    if (nCtlColor= = CTLCOLOR_EDIT )
    pDC —> SetTextColor (RGB (255, 0 , 0 , ) )

    return hbr
    }

    然而,因为每一个父窗体必须处理通知消息并指定每一个控件的绘画属性,所以。这样的方法不是全然的面向对象的方法。控件处理该消息并指定绘画属性更合情合理。

    消息反射同意用户这样做。通知消息首先发送给父窗体,假设父窗体没有处理则发送给控件。

    创建一个定制彩色列表框控件必须遵循下述步骤。

    首先。使用ClassWizard 创建一个CListBox 的派生类并为该类加入下述数据成员。
    class CMyListBox publilc CListBox
    {

    private
    COLORREF m_clrFor // foreground color
    COLORREF m_clrBack //background color
    Cbrush m_brush //background brush

    }
    其次,在类的构造函数中,初始化数据中。
    CMyListBox : : CMyListBox ()
    {
    //Initialize data members .
    m_clrFore =RGB (255 , 255 , 0) //yellow text
    m_clrBack=RGB (0 , 0 , 255) // blue background
    m_brush . CreateSolidBrush (m _clrBack )
    }

    最后,使用ClassWizard处理反射的WM_CTLCOLOR(=WM_CTLCOLOR)消息并指定新的绘画属性。
    HBRUSH CMyListBox : : CtlColor (CDC* pDC, UINT nCtlColor )
    {
    pDC—>SetTextColor (m_clrFore)
    pDC—>SetBkColor (m_clrBack)

    return (HBRUSH) m_brush.GetSafeHandle ()
    }
    如今。控件能够自己决定怎样绘画。与父窗体无关。
    (49) 当向列表框中加入多个项时怎样防止闪烁
    调用CWnd::SetRedraw 清除重画标志能够禁止CListBox(或者窗体)重画。当向列表框加入几个项时。用户能够清除重画标志,然后加入项,最后恢复重画标志。

    为确保重画列表框的新项,调用SetRedraw (TRUE) 之后调用CWnd::Invalidate。

    //Disable redrawing.
    pListBox->SetRedraw (FALSE)

    //Fill in the list box gere
    //Enable drwing and make sure list box is redrawn.
    pListBox->SetRedraw (TRUE)
    pListBox->Invalidate ()
    (50) 怎样向编辑控件中加入文本
    因为没有CEdit:: AppendText函数,用户仅仅好自己做此项工作。

    调用CEdit:: SetSel移动到编辑控件末尾,然后调用CEdit:: ReplaceSel加入文本。下例是AppendText 的一种实现方法:

    void CMyEdit:: AppendText (LPCSTR pText)
    {
    int nLen=GetWindowTextLength ()
    SetFocus ()
    SetSel (nLen, nLen)

    ReplaceSel (pText)
    }
    (51) 怎样訪问提前定义的GDI对象
    能够通过调用CDC:: SlectStockObject使用Windows的几个提前定义的对象。诸如刷子、笔以及字体。

    下例使用了Windows提前定义的笔和刷子GDI对象在视窗中画一个椭圆。


    //Draw ellipse using stock black pen and gray brush.
    void CSampleView:: OnDraw (CDC* pDC)
    {
    //Determine size of view.
    CRect rcView
    GetClientRect (rcView)

    //Use stock black pen and stock gray brush to draw ellipse.
    pDC->SelectStockObject (BLACK_PEN)
    pDC->SelectStockObject (GRAY_BRUSH)
    //Draw the ellipse.
    pDC->Ellipse (reView)
    }

    也能够调用新的SDK函数GetSysColorBrush获取一个系统颜色刷子,下例用背景色在视窗中画一个椭圆:
    void CsampleView:: OnDraw (CDC* pDC)
    {
    //Determine size of view.
    CRect rcView
    GetClientRect (rcView)

    //Use background color for tooltips brush.
    CBrush * pOrgBrush=pDC->SelectObject ( CBrush ::FromHandle( ::GetSysColorBrush (COLOR_INFOBK)))

    //Draw the ellipse.
    pDC->Ellipse (rcView)

    //Restore original brush.
    pDC->SelectObject (pOrgBrush)
    }
    (52) 怎样获取GDI对象的属性信息
    能够调用GDIObject:: GetObject。这个函数将指定图表设备的消息写入到缓冲区。

    下例创建了几个实用的辅助函数。


    //Determine if font is bold.
    BOOL IsFontBold (const CFont&font)
    {
    LOGFONT stFont
    font.GetObject (sizeof (LOGFONT), &stFont)
    return (stFont.lfBold)?

    TRUE: FALSE
    }

    //Return the size of a bitmap.
    CSize GetBitmapSize (const CBitmap&bitmap)
    {
    BITMAP stBitmap
    bitmap.GetObject (sizeof (BITMAP), &stBitmap)
    return CSize (stBitmap.bmWidth, stBitmap.bmHeight)
    }

    //Create a pen with the same color as a brush.
    BOOL CreatePenFromBrush (Cpen&pen, cost Cbrush&brush)
    {
    LOGBRUSH stBrush
    brush.Getobject (sizeof (LOGBRUSH), &stBrush)
    return pen. Createpen (PS_SOLID, 0, stBrush.ibColor)
    }
    (53) 怎样实现一个橡皮区矩形
    CRectTracker是一个非常实用的类,能够通过调用CRectTracker::TrackRubberBand 响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。
    下例表明使用CRectTracker移动和重置视窗中的蓝色椭圆的大小是非常easy的事情。

    首先。在文件档中声明一个CRectTracker数据成员:
    class CSampleView : Public CView
    {

    public :
    CrectTracker m_tracker

    }

    其次,在文档类的构造函数中初始化CRectTracker 对象:
    CSampleDoc:: CSampleDOC ()
    {
    //Initialize tracker position, size and style.
    m_tracker.m_rect.SetRect (0, 0, 10, 10)
    m_tracker.m_nStyle=CRectTracker:: resizeInside | CRectTracker ::dottedLine
    }

    然后。在OnDraw函数中画椭圆和踪迹矩形:
    void CSampleView:: OnDraw (CDC* pDC)
    {
    CSampleDoc* pDoc=GetDocument ()
    ASSERT_VALID (pDoc)

    //Select blue brush into device context.
    CBrush brush (RGB (0, 0, 255))
    CBrush* pOldBrush=pDC->SelectObject (&brush)

    //draw ellipse in tracking rectangle.
    Crect rcEllipse
    pDoc->m_tracker.GetTrueRect (rcEllipse)
    pDC->Ellipse (rcEllipse)

    //Draw tracking rectangle.
    pDoc->m_tracker.Draw (pDC)
    //Select blue brush out of device context.
    pDC->Selectobject (pOldBrush)
    }

    最后,使用ClassWizard处理WM_LBUTTONDOWN消息,并添加下述代码。该段代码依据鼠标击键情况能够拖放、移动或者重置椭圆的大小。
    void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)
    {
    //Get pointer to document.
    CSampleDoc* pDoc=GetDocument ()
    ASSERT_VALID (pDoc)

    //If clicked on ellipse, drag or resize it.Otherwise create a
    //rubber-band rectangle nd create a new ellipse.
    BOOL bResult=pDoc->m_tracker.HitTest (point)!= CRectTracker::hitNothing

    //Tracker rectangle changed so update views.
    if (bResult)
    {
    pDoc->m_tracker.Track (this,point,TRue)
    pDoc->SetModifiedFlag ()
    pDoc->UpdateAllViews (NULL)
    }

    else
    pDoc->m-tracker.TrackRubberBand(this,point,TRUE)
    CView:: onLButtonDown (nFlags,point)
    }
    (54) 怎样更新翻转背景颜色的文本
    调用CDC:: SetBkmode并传送OPAQUE用当前的背景颜色填充背景,或者调用CDC::SetBkMode并传送TRANSPAARENT使背景保持不变。这两种方法都能够设置背景模式。下例设置背景模式为TRANSPARENT,能够两次更新串。用花色带黑阴影更新文本。黑色串在红色串之后,但因为设置了背景模式仍然可见。

    void CSampleView:: OnDraw (CDC* pDC)
    {
    //Determint size of view.
    CRect rcView
    GetClientRect (rcVieew)

    //Create sample string to display.
    CString str (_T ("Awesome Shadow Text..."))
    //Set the background mode to transparent.
    pDC->SetBKMode (TRANSPARENT)

    //Draw black shadow text.
    rcView.OffsetRect (1, 1)
    pDc->SetTextColor (RGB (0, 0, 0))
    pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)

    //Draw red text.
    rcView.OffsetRect (-1,-1)
    pDc->SetTextColor (RGB (255, 0, 0))
    pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)

    }
    (55) 怎样创建一个具有特定点大小的字体
    能够指定字体逻辑单位的大小。但有时指定字体的点的大小可能会更方便一些。

    能够例如以下将字体的点转换为字体的高度:

    int nHeigth=mulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72)
    下例创建了一个8点的Apial字体:

    CClientDC dc (AqfxGetMainWnd ())

    m_font. CreateFont (MulDiv (8, -dc.GetDeviceCaps (LOGPIXELSY), 72), 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF-SWISS,_T("Arial"))
    (56) 怎样计算一个串的大小
    函数CDC:: Det text Extent 根据当前选择的字体计算一个串的高度和宽度。

    假设使用的不是系统字体而是其它字体,则在调用GetTextExtent之前将字体选进设备上下文中是非常重要的,否则计算高度和宽度时将根据系统字体,由此得出的结果当然是不对的。下述样板程序当改变下压button的标题时动态调整button的大小,button的大小由button的字体和标题的大小而定。响应消息WM_SETTEXT时调用OnSetText,该消息使用ON_MESSAE宏指令定义的用户自己定义消息。

    LRESULT CMyButton:: OnSettext (WPARAM wParam, LPARAM lParam)
    {
    //Pass message to window procedure.
    LRESULT bResult=CallWindowProc (*GetSuperWndProcAddr(), m_hWnd, GetCurrentMessage() ->message,wParam,lParam)
    //Get title of push button.
    CString strTitle
    GetWindowText (strTitle)

    //Select current font into device context.
    CDC* pDC=GetDc ()
    CFont*pFont=GetFont ()
    CFont*pOldFont=pDC->SelectObject (pFont)

    //Calculate size of title.
    CSize size=pDC->GetTextExent (strTitle,strTitle.GetLength())

    //Adjust the button's size based on its title.
    //Add a 5-pixel border around the button.
    SetWindowPos (NULL, 0, 0, size.cx+10, size.cy+10, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE)
    //Clean up.
    pDC->SelectFont (pOldFont)
    ReleaseDC (pDC)

    return bResult
    }

    (57) 怎样显示旋转文本
    仅仅要用户使用TrueType或者GDI笔或字体就能够显示旋转文本(有些硬件设备也支持旋转光栅字体)。LOGFONT结构中的ifEscapement成员指定了文本行和x轴的角度,角度的单位是十分之中的一个度而不是度,比如。ifEscapement为450表示字体旋转45度。为确保全部的字体沿坐标系统的同一方向旋转。一定要设置ifEscapement成员的CLIP_LH_ANGLES位,否则。有些字体可能反向旋转。下例使用了14点Arial字体每间隔15度画一个串。
    void CSampleView:: OnDraw (CDC* pDC)
    {
    //Determine the size of the window.
    CRect rcClient
    GetClientRect (rcClient)

    //Create sample string.
    CString str (_T ("Wheeee...I am rotating!"))
    //Draw transparent, red text.
    pDC->SetBkMode (TRANSPARENT)
    pDC->SetTextColor (RGB (255,0,0))
    CFont font
    //font object
    LOGFONT stFont //font definition
    //Set font attributes that will not change.
    memset (&stFont, 0, sizeof (LOGFONT))
    stFont.ifheight=MulDiv (14, -pDC->GetDeviceCaps(LOGPIXELSY), 72)
    stFont.ifWeight=FW_NORMAL
    stFont.ifClipPrecision=LCIP_LH_ANGLES
    strcpy (stFont.lfFaceName, "Arial")

    //Draw text at 15degree intervals.
    for (int nAngle=0 nAngle<3600 nAngle+=150)
    {
    //Specify new angle.
    stFont.lfEscapement=nAngle

    //Create and select font into dc.
    font.CreateFontIndirect(&stfont)
    CFont* pOldFont=pDC ->SelectObject(&font)

    //Draw the text.
    pDC->SelectObject(pOldFont)
    font.DelectObjext()
    }
    }

    (58) 怎样正确显示包括标签字符的串
    调用GDI文本绘画函数时须要展开标签字符。这能够通过调用CDC:: TabbedTextOut或者CDC:: DrawText并指定DT_EXPANDTABS标志来完毕。TabbedTextOut函数同意指定标签位的数组。下例指定每20设备单位展开一个标签:

    void CSampleView:: OnDraw (CDC* pDC)
    {
    CTestDoc* pDoc=GetDocument ()
    ASSERT_VALID (pDoC)

    CString str
    str.Format (_T ("Cathy Norman Oliver"))
    int nTabStop=20 //tabs are every 20 pixels
    pDC->TabbedtextOut (10, 10, str, 1, &nTabStop, 10)
    }
    (59) 怎样高速地格式化一个CString对象
    调用CString:: Format,该函数和printf函数具有同样的參数,下例说明了怎样使用Format函数:

    //Get size of window.
    CRect rcWindow
    GetWindowRect (rcWindow)
    //Format message string.
    CString strMessage
    strMessage.Format (_T ("Window Size (%d, %d)"),

    rcWindow.Width (), rcWindow.Height ())

    //Display the message.
    MessageBox (strmessage)
    (60) 串太长时怎样在其末尾显示一个省略号
    调用CDC:: DrawText并指定DT_END_ELLIPSIS标志,这样就能够用小略号代替串末尾的字符使其适合于指定的边界矩形。假设要显示路径信息,指定DT_END_ELLIPSIS标志并省略号代替串中间的字符。

    void CSampleView:: OnDraw (CDC* pDC)
    {
    CTestDoc* pDoc=GetDocument ()
    ASSERT_VALID (pDoc)

    //Add ellpsis to end of string if it does not fit
    pDC->Drawtext (CString ("This is a long string"), CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS)

    //Add ellpsis to middle of string if it does not fit
    pDC->DrawText (AfxgetApp () ->m_pszhelpfilePath, CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS)
    }

    (61) 为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态
    须要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,假设该数据成员为TRUE(缺省值),工作框将自己主动地禁止没有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜单项。

    //Disable MFC from automatically disabling menu items.
    m_bAuoMenuEnable=FALSE
    //Now enable the menu item.
    CMenu* pMenu=GetMenu ()
    ASSERT_VALID (pMenu)

    pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED)

    (62) 怎样给系统菜单加入一个菜单项
    给系统菜单加入一个菜单项须要进行下述三个步骤:
    首先,使用Resource Symbols对话(在View菜单中选择Resource Symbols...能够显示该对话)定义菜单项ID,该ID应大于0x0F而小于0xF000。
    其次。调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd:: Appendmenu将菜单项加入到菜单中。

    下例给系统菜单加入两个新的
    int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
    {

    //Make sure system menu item is in the right range.
    ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM)
    ASSERT (IDM-MYSYSITEM<0xF000)

    //Get pointer to system menu.
    CMenu* pSysmenu=GetSystemmenu (FALSE)
    ASSERT_VALID (pSysMenu)
    //Add a separator and our menu item to system menu.
    CString StrMenuItem (_T ("New menu item"))
    pSysMenu->Appendmenu (MF_SEPARATOR)
    pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem)


    }

    如今。选择系统菜单项时用户应进行检測。

    使用ClassWizard处理WM_SYSCOMMAND消息并检測用户菜单的nID參数:
    void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)
    {
    //Determine if our system menu item was selected.
    if ( (nID & 0xFFF0)==IDM_MYSYSITEM)
    {
    //TODO-process system menu item
    }

    else
    CMDIFrameWnd ::OnSysCommand (nID, lParam)
    }
    最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这能够通过添加一个包括系统菜单基ID的串表的入口来实现。
    (63) 怎样确定顶层菜单所占领的菜单行数
    这能够通过简单的减法和除法来实现。首先,用户须要计算主框窗体的高度和客户区。其次,从主框窗体的高度中减去客户区、框边界以及标题的高度;最后,除以菜单条的高度。下例成员函数是一个计算主框菜单所占领的行数的代码实现。

    int CMainFrame:: GetMenuRows ()
    {
    CRect rcFrame,rcClient
    GetWindowRect (rcFrame)
    GetClientRect (rcClient)
    return (rcFrame.Height () -rcClient.Height () - :: GetSystemMetrics(SM_CYCAPTION) - (:: getSystemMetrics(SM_CYFRAME) *2)) / :: GetSystemMetrics(SM_CYMENU)
    }
    (64) 在用户环境中怎样确定系统显示元素的颜色
    调用SDK函数GetSysColor能够获取一个特定显示元素的颜色。下例说明了怎样在MFC函数CMainFrameWnd:: OnNcPaint中调用该函数设置窗体标题颜色。

    void CMiniFrameWnd:: OnNcPaint ()
    {

    dc.SetTextColor (:: GetSysColor (m_bActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT))


    (65) 怎样查询和设置系统參数
    在Windows 3.1 SDK中介绍过SDK函数SystemParametersInfo,调用该函数能够查询和设置系统參数。诸如按键的反复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。



    //Create a font that is used for icon titles.
    LOGFONT stFont
    ∶: SystemParametersInfo (SPIF_GETICONTITLELOGFONT, sizeof (LOGFONT), &stFont, SPIF_SENDWININICHANGE)
    m_font.CreateFontIndirect (&stFont)

    //Change the wallpaper to leaves.bmp.
    ∶ : SystemParametersInfo (SPI_SETDESKWALLPAPER, 0, _T (" forest.bmp"), SPIF_UPDATEINIFILE)

    (66) 怎样确定当前屏幕分辨率
    调用SDK函数GetSystemMetrics。该函数能够检索有关windows显示信息,诸如标题大小、边界大小以及滚动栏大小等等。

    //Initialize CSize object with screen size.
    CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),
    GetSystemMetrics (SM_CYSCREEN))

    (67) 怎样使用一个提前定义的Windows光标
    调用CWinApp:: LoadStandardCursor并传送光标标识符。
    BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd,
    UINT nHitTest, UINT
    message)
    {
    //Display wait cursor if busy.
    if (m_bBusy)
    {
    SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT))
    return TRUE
    }

    return CDialog:: OnSetCursor (pWnd. nHitTest,message)
    }
    (68) 怎样检索原先的Task Manager应用程序使用的任务列表
    原先的Task Manager应用程序显示顶层窗体的列表。为了显示该列表,窗体必须可见、包括一个标题以及不能被其它窗体拥有。调用CWnd:: GetWindow能够检索顶层窗体的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwner能够确定窗体是否应该在列表中。下例将把TaskManager窗体的标题填充到列表中。

    void GetTadkList (CListBox&list)
    {
    CString strCaption
    //Caption of window.

    list.ResetContent ()
    //Clear list box.

    //Get first Window in window list.
    ASSERT_VALID (AfxGetMainWnd ())
    CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST)

    //Walk window list.
    while (pWnd)
    {
    // I window visible, has a caption, and does not have an owner?
    if (pWnd ->IsWindowVisible()
    && pWnd ->GetWindowTextLength ()
    &&! pWnd ->GetOwner ())
    {

    //Add caption o window to list box.

    pWnd ->GetWindowText (strCaption)

    list.AddString (strCaption)
    }
    //Get next window in window list.
    pWnd=pWnd ->GetWindow(GW_HWNDNEXT)
    }
    }
    (69) 怎样确定Windows和Windows系统文件夹
    有两个SDK函数能够完毕该功能。GetWindowsDirectory和GetSystemDirectory,下例说明了怎样使用这两个函数:

    TCHAR szDir [MAX_PATH]
    //Get the full path of the windows directory.
    ∶ : GetWindowsDirectory (szDir, MAX_PATH)
    TRACE ("Windows directory %s ", szDir)
    //Get the full path of the windows system directory.
    ∶ : GetSystemDirectory (szDir, MAX_PATH)
    TRACE ("Windows system directory %s ", szDir)
    (70) 在哪儿创建临文件
    调用SDK函数GetTemPath能够确定暂时文件的文件夹,该函数首先为暂时路径检測TMP环境变量:假设没有指定TMP。检測TMP环境变量。然后返回到当前文件夹。

    下例说明了怎样创建一个暂时文件。


    //get unique temporary file.
    CString strFile
    GetUniqueTempName (strFile)
    TRY
    {
    //Create file and write data.Note that file is closed
    //in the destructor of the CFile object.
    CFile file (strFile,CFile ::modeCreate | Cfile:: modeWrite)

    //write data
    }

    CATCH (CFileException, e)
    {
    //error opening file
    }
    END_CATCH


    Void GetuniqueTempName (CString& strTempName)
    {
    //Get the temporary files directory.
    TCHAR szTempPath [MAX_PATH]
    DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath)
    ASSERT (dwResult)

    //Create a unique temporary file.
    TCHAR szTempFile [MAX_PATH]
    UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile)
    ASSERT (nResult)

    strTempName=szTempFile
    }
    (71) 我如何才干建立一个等待光标?


    调 用 BeginWaitCursor 函 数 来 启 动 等 待 光 标,调 用 EndWaitCursor 函 数 来 结 束 等 待 光 标。要 注 意。二 者 都 要 调 用 app 的 成 员 函 数。如 下 所 示:

        AfxGetApp()->BeginWaitCursor();
        // 要做的事
        AfxGetApp()->EndWaitCursor();
    (72) 我在MDI框架中有个 form 视窗。它有个取消button。我须要当用户按取消button时可关闭form视窗。我应该怎样关闭该文档?
    调 用 OnCloseDocument 函 数。


    (73) 怎样訪问桌面窗体
    静态函数CWnd:: GetDesktopWindow 返回桌面窗体的指针。

    下例说明了MFC函数CFrameWnd::BeginModalStae是怎样使用该函数进入内部窗体列表的。

    void CFrameWnd::BeginModalState ()
    {

    //first count all windows that need to be disabled
    UINT nCount=0
    HWND hWnd= :: GetWindow (:: GetDesktopWindow(), GW_CHILD)
    while (hWnd!=NULL)
    {
    if (:: IsWindowEnabled (hwnd)
    && CWnd::FromHandlePermanent (hWnd)!=NULL
    && AfxIsDescendant (pParent->m_hWnd, hWnd)
    && :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0)
    {
    ++nCount
    }
    hWnd=:: GetWindow (hWnd, GW_HWNDNEXT)
    }

    (74) 什么是COLORREF? 我该如何用它?


    COLORREF 是 一 个 32-bit 整 型 数 值,它 代 表 了 一 种 颜 色。

    你 可 以 使 用 RGB 函 数 来 初 始 化 COLORREF。例 如:

        COLORREF color = RGB(0, 255, 0);
    RGB 函 数 接 收 三 个 0-255 数 值,一 个 代 表 红 色, 一 个 代 表 绿 色, 一 个 代 表 蓝 色。

    在 上 面的 例 子 中, 红 色 和 蓝 色 值 都 为 0,所 以 在 该 颜 色 中 没 有 红 色 和 蓝 色。绿 色 为 最 大 值 255。

    所 以 该 颜 色 为 绿 色。0,0,0 为 黑 色。255,255,255 为 白 色。



    另 一 种 初 始 化 COLORREF 的 方 法 如 下 所 示:

        CColorDialog colorDialog;
        COLORREF color;

        if( colorDialog.DoModal() == IDOK )
        {
            color = colorDialog.GetColor();
        }
    这 段 代 码 使 用 了 MFC 中 的 颜 色 对 话 框,它 需 要 文 件。

    (75) AppWizard所产生的STDAFX文件是干什么用的?
    它 主 要 是 协 助 产 生 预 编 译 头 文 件 的。通 常 你 是 不 需 要 修 改 它 的。
    (76) 我在我的程序中是了CDWordArray。

    我向它加入了约10,000个整数,这使得它变得很很慢。为什么会这么糟?
    CDWordArray 是 非常 好 用 的,仅仅 是 因 为 你 没 有 指 定 数 组 的最大尺寸。因 此,当 你 添 加 新 元 素 时。该 类 会 从 堆 中 重 新 分 配 空 间。不 幸 的 是,该 类 会 在 每 次 插 入 新 元 素 时 都 为 数 组 重 新 分 配 空 间。如 果 你 向 它 添 加 了 非常 多 新 元 素,所 有 这 些 分 配 和 复 制 数 组 的 操 作 会 就 会 使 它 变 慢。

    解 决 该 问 题 的 方 法 是,你 可 以 使 用 SetSize 函 数 的 第 二 个 參 数 来 改 变 这 种 重 新 分 配 的 频 率。例 如。如 果 你 把 该 參 数 设 置 为 500,则 每 次 数 组 空 间 超 出 时 它 才 重 新 分 配 并 添 加 500 个 新 空 间,而 不 是 1 个。这 样 一 来,你 就 可 以 不 用 重 新 分 配 而 添 加 了 另 外 499 个 元 素 空 间,这 也 会 大 大 提 高 程 序 的 运 行 速 度。

    (77) 我该怎样改变MDI框架窗体的子窗体的大小以使在窗体以一定的大小打开?
    在 视 中 的 OnInitialUpdate 函 数 中 调 用 GetParentFrame 函 数。GetParentFrame 会 返 回 一 指 向 一 保 存 有 该 视 的 框 架 窗 口 的 指 针。然 后 调 用 在 框 架 窗 口 上 调 用 MoveWindow。


    (78) 在我的程序的某些部分,我能够调用 MessageBox 函数来建立一个信息对话框。比如在视类中。可是,在其他部分我却不能,如文档类中。

    为什么?我如何才干在我的应用程序类中建立一个信息对话框?
    MessageBox 函 数 来 自 CWnd 类,所 以 你 仅仅 能 在 从 CWnd 继 承 的 类 ( 如 CView ) 中 调 用 它。但 是,MFC 也 提 供 了 AfxMessageBox 函 数,你 可 以 在 任 何 地 方 调 用 它。

    (79) 我须要在我的程序中设置全局变量,以使文档中的全部类都能訪问。我应该吧它放到哪儿?


    把 该 变 量 放 到 该 应 用 程 序 类 的 头 文 件 中 的 attribute 处。然 后。在 程 序 的 任 何 地 方,你 都 可 以 用 下 面 的 方 法 来 訪 问 该 变 量:

        CMyApp *app = (CMyApp *)AfxGetApp();
        app->MyGlobalVariable = ...
    (80) 我听说MFC能够发现内存漏洞,我如何使用该特性?
    如 果 你 在 Debug 菜 单 中 的 Go 选 项 ( 不 是 Project 菜 单 中 的 Execute 选 项 ) 来 运 行 你 的 应 用 程 序,MFC 应 该 在 程 序 终 止 时 报 告 内 存 漏 洞。如 果 没 有,那 么 试 试 运 行 MFC Tracer 工 具 程 序 ( 在 VC++ 程 序 组 中 )。并 启 动 跟 踪。然 后 返 回 应 用 程 序。


    (81) 我如何才干在我的应用程序中循环浏览已经打开的文档?
    使用CDocTemplate中未公开的GetFirstDocPosition()和GetNextDoc()函数。 

    (82)才干在我的应用程序中循环浏览已经打开的视?
    使 用 CDocument 中 未 公 开 的 GetFirstViewPosition() 和 GetNextView() 函 数。
    (83)数PreCreateWindow是干什么用的?
    PreCreateWindow 允 许 你 在 调 用 CreateWindow 之 前 来 改 变 窗 口 属 性。
    (84)该如何防止MFC在窗体标题栏上把文档名预置成应用程序名?
    在 PreCreateWindow 函 数 中 删 除 FWS_PREFIXTITLE 标 志 的 窗 口 样 式:

        cs.style &= ~FWS_PREFIXTITLE;

    (85) 我应该如何防止MFC在窗体标题栏上加入文档名?


    在 PreCreateWindow 函 数 中 删 除 FWS_ADDTOTITLE 标 志 的 窗 口 样 式:

        cs.style &= ~FWS_ADDTOTITLE ;

    (86) 我应该怎样改变视窗体的大小?
    因 为 视 窗 口 实 际 上 是 框 架 窗 口 的 子 窗 口。所 以 你 必 须 改 变 框 架 窗 口 的 大 小,而 不 是 改 变 视 窗 口。使 用 CView 类 中 的 GetParentFrame() 函 数 获 得 指 向 框 架 窗 口 的 指 针。然 后 调 用 MoveWindow() 函 数 来 改 变 框 架 的 大 小。这 会 使 变 尺 寸 的 视 充 满 框 架 窗 口。


    (87) 我有一无模式对话框。我如何才干在窗体退出时删除CDialog对象?
    把“delete this”加 到 PostNcDestroy 中。这 主 要 用 在 需 要 自 动 删 除 对 象 的 场 合。



    (88) 为什么把“delete this”放在PostNcDestroy中而不是OnNcDestroy?
    OnNcDestroy 仅仅 被 已 建 立 的 窗 口 调 用。如 果 建 立 窗 口 失 败 ( 如 PreCreateWindow ),则 没 有 窗 口 处 来 发 送 WM_NCDESTROY 消 息。

    PostNcDestroy 是 在 对 象 窗 口 被 完 全 删 除,在 OnNcDestroy 后,甚 至 在 窗 口 建 立 失 败 之 后 调 用 的。



    (89) File菜单中的MRU列表是从哪儿来的?列表中的名字放在哪儿了?我如何才干改变列表中项目的最大值?
    在 应 用 程 序 类 的 InitInstance 函 数 中 对 LoadStdProfileSettings 的 调 用 中。

    该 调 用 接 受 一 个 參 数 ( 在 缺 省 情 况 下 如 果 没 有 传 递 值 则 为 4 )。MRU 文 件 名 是 从 INI 文 件 中 调 用 的。如 果 你 有 带 有 ID_FILE_MRU_FILE1 的 ID 的 菜 单 选 项,它 会 为 调 入 的 MRU 列 表 所 替 换。如 果 你 改 变 传 递 给 LoadStdProfileSettings 的 数 值 ( 最 大 为 16 ),则 你 就 改 变 了 所 装 如 文 件 名 的 最 大 值。
    (90) 我在菜单中加入了新的项。

    可是,当我选该项时,在状态栏上没有出现不论什么提示信息。

    为什么?
    打 开 资 源 文 件 中 的 菜 单 模 板。打 开 新 菜 单 选 项 的 属 性 对 话 框。在 对 话 框 的 底 部 的 Prompt 编 辑 框 中 ,你 可 以 如 下 指 定 状 态 栏 上 的 提 示 信 息 和 工 具 栏 上 的 提 示 信 息 ( 如 果 你 已 经 建 立 的 工 具 栏 按 钮 ):

        Status bar string Flying tag
    (91) 我如何才干在应用程序的缺省系统菜单中加上一些东西?
    系 统 菜 单 与 其 它 菜 单 类 似。你 可 以 添 加 或 删 除 项 目。这 需 要 使 用 CMenu 类 的 成 员 函 数。下 面 的 代 码 在 你 的 系 统 菜 单 后 面 添 加 一 个 新 菜 单 项:

        CMenu *sysmenu;
        sysmenu = m_pMainWnd->GetSystemMenu(FALSE);
        sysmenu->AppendMenu(MF_STRING, 1000, "xxx");
    參 见 MFC 帮 助 文 件 中 的 CMenu 类。


    (92) 我建立了一个对话框。可是当我显示该对话框时,第一个编辑框总是不能获得焦点,我必须单击它来使它获得焦点。我如何才干使第一个编辑框在对话框打开时就获得焦点?
    打 开 资 源 编 辑 器 中 的 对 话 框 模 板。在 Layout 菜单 中 选 择 Tab Order 选 项。

    按 你 的 需 求 单 击 对 话 框 中 的 控 制 来 重 新 排 列 这 些 控 制 的 tab 顺 序。


    (93) 我如何才干使一个窗体具有“always on top”特性?
    在 调 用 OnFileNew 后,在 你 的 InitInstance 函 数 中 加 上 下 面 的 代 码:

    m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
    (94)   我要为我的form view加入文档模板。我先建立了对话框模板,然后使用ClassWizard建立了基于CFormView的新类,它也是从CDocument继承来的。我还建立了对应的资源并在InitInstance中加入了新的文档模板。可是,当我试图执行该程序时,出现了Assertion信息。

    为什么?


    form 的 对 话 框 模 板 需 要 些 特 殊 设 置 以 便 可 用 于 CFromView。确 保 这 些 设 置 的 最 简 单 方 法 是 使 用 AppWizard 来 建 立 CFormView 应 用 程 序。并 查 看 AppWizard 所 建 立 的 对 话 框 模 板 所 选 择 的Styles Properties。你 会 发 现 该 对 话 框 模 板 具 有 下 列 样 式:没 有 标 题 栏、不 可 见 和“Child”。

    把 你 的 form view 的 对 话 框 属 性 变 成 这 样 就 可 以 了。

    (95)   我在一对话框中有一列表框,我须要tabbed列表框中的项目。可是,当我处理含有tab字符(用AddString加入的)的列表项时,tab被显示成小黑块而没有展开。

    哪儿出错了?
    在 对 话 框 模 版 中。打 开 列 表 框 的 属 性。确 保 选 择 了“Use Tabstops” 样 式。然 后,确 保 在 对 话 框 类 中 OnInitDialog 函 数 中 调 用 SetTabStops。

    (96)  我建立了一个应用程序,并使用了CRecordset类。可是,当我执行该程序时,它试图要訪问数据库,并给出“Internal Application Error”对话框。我应该如何做?
    通 常 情 况 下,当 你 的 程 序 中 向 数 据 库 发 送 信 息 的 SQL 语 句 出 现 问 题 时 才 出 现 该 对 话 框。例 如,參 见 下 面 的 例 子:

        set.m_strFilter = "(ZipCode = '27111')";
    如 果 ZipCode 列 被 定 义 为 字 符 串 时 不 会 出 现 问 题。如 果 定 义 为 long。则 会 出 现“Internal Application Error”对 话 框,这 是 由 于 类 型 不 匹 配 的 缘 故。如 果 你 删 除 27111 的 单 引 号。则 不 会 出 现 问 题。

    当 你 看 到“Internal Application Error”时,最 好 检 查 一 下 试 图 要 发 送 给 数 据 库 的 SQL 语 句。



    (97)   我用ClassWizard建立了一个类。可是,我把名字取错了,我想把它从项目中删除,应该怎样做?


    在 ClassWizard 对 话 框 关 闭 后,用 文 件 管 理 器 删 除 新 类 的 H 和 CPP 文 件。然 后 打 开 ClassWizard,它 会 提 示 丢 失 了 两 个 文 件,并 询 问 你 该 如 何 做。

    你 可 以 选 择 从 项 目 中 删 除 这 两 个 问 的 按 钮。

    (98)     当我打开应用程序中的窗体时,我要传递该窗体的矩形尺寸。

    该矩形指定了窗体的外围大小,可是当我调用GetClientRect时,所得到的尺寸要比所希望的值要小(由于工具栏和窗体边框的缘故)。有其他方法来计算窗体的尺寸吗?


    參 见 CWnd::CalcWindowRect。

    (99)   我在文档类中设置了一个整型变量。

    可是,当我试图把该变量写入Serialize函数中的archive文件里时,出现了类型错误。而文档中的其他变量没有问题。为什么?


    archive 类 仅仅 重 载 某 些 类 型 的 >> 和 << 操 作 符。“int”类 型 没 有 在 其 中。也 许 是 因 为 int 变 量 在 Windows 3.1 与 Windows NT/95 有 所 不 同 的 缘 故 吧。“long”类 型 得 到 了 支 持,所 以 你 可 以 把 int 类 型 改 成 long 型。參 见 MFC 帮 助 文 件 中 CArchive 类。


    (100)  怎样控制菜单的大小?
    我用MFC的CMenu生成了一个动态菜单(比如File,Edit,View...Help), 我想控制这个菜单的大小(长+高).
    方法一:查找 WM_MEASUREITEM 和 MEASUREITEMSTRUCT.
    方法二:查询系统::GetSystemMetric(SM_CXMENUSIZE).
         /* 你能够通过例如以下代码来获得文本的大小:
            (A)获得被使用的字体 */
           NONCLIENTMETRICS ncm;
         HFONT hFontMenu;
         SIZE size;
         size.cy = size.cy = 0;
         memset(&ncm, 0, sizeof(NONCLIENTMETRICS));
         ncm.cbSize = sizeof(NONCLIENTMETRICS);
         if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
         {
              hFontMenu = CreateFontIndirect(&ncm.lfMenuFont);
              /*
              (B) 获得菜单项的文本: */
              char szText[_MAX_PATH];
              pMenu->GetMenuString(0, szText, _MAX_PATH, MF_BYPOSITION);
              /*
              然后,获得菜单项文本的高度: */
              HFONT hFontOld;
              HDC hDC;
              hDC = ::GetDC(NULL);
              hFontOld = (HFONT) ::SelectObject(hDC, hFontMenu);
              GetTextExtentPoint32(hDC, szText, lstrlen(szText), &size);
              SelectObject(hDC, hFontOld);
              ::ReleaseDC(NULL, hDC);
         }
         /*此时,size.cy即为高度,size.cx为宽度,你能够给菜单加上自己定义的高度和宽度,通过比較,我发现宽度为4
    比較合适。

    */

    (101)  改变LVIS_SELECTED的状态颜色?


    我想将CListCtrl项和CTreeCtrl项在LVIS_SELECTED状态时的颜色变灰.
    方法一:查找函数CustomDraw,它是IE4提供的公共控制,同意有你自己的代码.
    方法二:生成一个draw控件,然后在DrawItem中处理文本颜色.
    (102)   怎样仅仅存储文档的某一部分?
    我仅仅想存储文档的某一部分,是否能象使用文件一样使用文档?(也就是有定位函数).将每一个CArchive类设置为CFile类的派生类,这样你就能使用Seek等成员函数.
    (103)   保存工具条菜单有bug吗?



    使用浮动菜单栏时,SaveBarState和LoadBarState出现了问题.假设菜单是浮动的,重起应用程序时它会出如今左上角,而它固定在屏幕其他位置时,下一次启动就会出如今该位置,这是什么原因?

    你试试这个PToolBar->Create(this,...,ID_MYTOOLBAR);
    你的工具条须要包含id,而不是象默认的工具条那样.
    (104)   Tip of the day的bug
    我创建了一个简单的mdi应用程序,使用.BSF(自己定义的文档扩展名)作为它的文档我保存一个foo.bsf文档后,能够在资源管理器中双击该文件打开mdi应用程序同一时候打开foo.bsf文档.但当我给mdi应用程序加上a tip of the day组件之后,从资源管理器中双击foo.bsf后,就会给我一个警告:ASSERT(::IsWindow(m_hWnd)),然后mdi应用程序就死那了.

    当从dde启动应用程序(比如:双击相关文档)时,"Tip of the Day"是有bug的.你能够看看函数"ShowTipAtStartup",它在"InitInstance"中调用,能够看到tip of the day作为一个模式对话框显示,在处理其他消息时它一直进行消息循环你可心改动ShowTipAtStartup使其从dde启动时不出现tip of the day.
    void CTipOfApp::ShowTipAtStartup(void)
            {
                    // CG: This function added by 'Tip of the Day' component.

                    CCommandLineInfo cmdInfo;
                    ParseCommandLine(cmdInfo);

                    if (
                            cmdInfo.m_bShowSplash &&
                            cmdInfo.m_nShellCommand != CCommandLineInf:FileDDE
                            )
                    {
                            CTipDlg dlg;
                            if (dlg.m_bStartup)
                                    dlg.DoModal();
                    }
            }
    假设还有其他bug,你能够设定cmdInfo.m_nShellCommand的过滤.

    (105)   怎样能够让我的程序能够显示在其他的窗体上面?

    让用户选择"总是在最上面"最好是在系统菜单里增加一个选项.能够通过改动WM_SYSCOMMAND消息来发送用户的选择.菜单的命令标识(id)会作为一个參数传给OnSysCommand().要定义标识(id),将例如以下代码增加到CMainFrame.CPP中:

        #define WM_ALWAYSONTOP WM_USER + 1
    将"总在最上面"的菜单项增加到系统菜单中,将例如以下代码增加到函数CMainFrame::OnCreate()中:

          CMenu* pSysMenu = GetSystemMenu(FALSE);
          pSysMenu->AppendMenu(MF_SEPARATOR);
          pSysMenu->AppendMenu(MF_STRING, WM_ALWAYSONTOP,
                         "&Always On Top");
    使用ClassWizard,增加对WM_SYSCOMMAND消息的处理,你应该改变消息过滤器,使用系统能够处理这个消息.
    void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
    {
        switch ( nID )
        {
        case WM_ALWAYSONTOP:

            if ( GetExStyle() & WS_EX_TOPMOST )
            {
                SetWindowPos(&wndNoTopMost, 0, 0, 0, 0,
                    SWP_NOSIZE | SWP_NOMOVE);
                GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,
                    MF_UNCHECKED);
            }
            else
            {
                SetWindowPos(&wndTopMost, 0, 0, 0, 0,
                    SWP_NOSIZE | SWP_NOMOVE);
                GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,MF_CHECKED);
            }

            break;

        default:
            CFrameWnd::OnSysCommand(nID, lParam);
        }
    }

    (106)    怎样控制窗体框架的最大最小尺寸?


    要控制一个框架的的最大最小尺寸,你须要做两件事情.在CFrameWnd的继承类中处理消息WM_GETMINMAXINFO,结构MINMAXINFO设置了整个窗体类的限制,因此记住要考虑工具条,卷动条等等的大小.

    // 最大最小尺寸的象素点 - 演示样例
    #define MINX 200
    #define MINY 300
    #define MAXX 300
    #define MAXY 400

    void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
    {
        CRect rectWindow;
        GetWindowRect(&rectWindow);

        CRect rectClient;
        GetClientRect(&rectClient);

          // get offset of toolbars, scrollbars, etc.
        int nWidthOffset = rectWindow.Width() - rectClient.Width();
        int nHeightOffset = rectWindow.Height() - rectClient.Height();

        lpMMI->ptMinTrackSize.x = MINX + nWidthOffset;
        lpMMI->ptMinTrackSize.y = MINY + nHeightOffset;
        lpMMI->ptMaxTrackSize.x = MAXX + nWidthOffset;
        lpMMI->ptMaxTrackSize.y = MAXY + nHeightOffset;
    }
    第二步,在CFrameWnd的继承类的PreCreateWindow函数中去掉WS_MAXIMIZEBOX消息,否则在最大化时你将得不到预料的结果.

    BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
    {
        cs.style &= ~WS_MAXIMIZEBOX;
        return CFrameWnd::PreCreateWindow(cs);
    }

    (107)    怎样改变窗体框架的颜色?


    MDI框架的客户区被还有一个窗体的框架所覆盖.为了改变客户区的背景色,你须要重画这个客户窗体.为了做到这点,你要处理消息WM_ERASEBKND产生一个新类,从CWnd继承,姑且称之为CMDIClient.给它加上一个成员变量,
    #include "MDIClient.h"
    class CMainFrame : public CMDIFrameWnd
    {
    ...
    protected:
    CMDIClient m_wndMDIClient;
    }
    在CMainFrame中重载CMDIFrameWnd::OnCreateClient
    BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
    {
        if ( CMDIFrameWnd::OnCreateClient(lpcs, pContext) )
        {
            m_wndMDIClient.SubclassWindow(m_hWndMDIClient);
            return TRUE;
        }
        else
            return FALSE;
    }
    然后就能够增加对消息WM_ERASEBKGND的处理了.

    (108)    怎样将应用程序窗体置于屏幕正中?


    要将你的应用程序窗体放置在屏幕正中央,仅仅须在MainFrame的OnCreate函数中增加:
    CenterWindow( GetDesktopWindow() );

  • 相关阅读:
    Annotation
    GIT的作用以及Versioncontrol为什么要用GIT
    Http协议
    人工智能的可怕与不可怕
    Makefile简易教程
    Node.js 学习笔记之一:学习规划 & 认知 Node.js
    《大教堂与集市》的启示 — 软件工程的另一种选择
    Git简易教程
    谈谈买书与读书
    clang编译器简介
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/6872095.html
Copyright © 2020-2023  润新知