window 编程指南(一)

news/2024/7/4 19:16:02

 
1. 如何获取应用程序的实例句柄?
    应用程序的实例句柄保存在CWinAppIm_hInstance 中,可以这么调用
    AfxGetInstancdHandle获得句柄.
      Example: HANDLE hInstance=AfxGetInstanceHandle();
 
   2. 如何通过代码获得应用程序主窗口的指针?
     主窗口的指针保存在CWinThread::m_pMainWnd中,调用 AfxGetMainWnd实现。
      AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED); //使程序最大化.
 
   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的重新引导?
      这是个很简单又是编程中经常要遇到的问题.
     第一问,向窗口发送 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开发人员指南"一书有比较详细的介绍,这里就不再多说乐。
 
 第二问,Use ExitWindowsEx Function函数控制系统是重新引导,还是重启
windows.
   前面已经有人讲过乐,就不再提了。
 
   5.怎样加栽其他的应用程序?
    我记得这好象是出场频度很高的问题。
    三个SDK函数 winexec, shellexecute,createprocess可以使用。
     WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数
 
 值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加栽一个无最大化按钮的程序,呵

 就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。
    ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的 Example就是直接
 
 打开 c:/temp/1.txt,而不用加栽与 txt文件关联的应用程序,很多安装程序完成后
 都会打开一个窗口,来显示Readme or Faq,偶猜就是这么作的啦.
 
ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c://temp"),SW_SHOWMAXMIZED);
    CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以
 
    指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的 Example:
       STARTUPINFO stinfo;   //启动窗口的信息
       PROCESSINFO procinfo; //进程的信息
 
     CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE, NORMAL_PRIORITY_
 
       CLASS,NULL,NULL, &stinfo,&procinfo);
 
    6. 确定应用程序的路径
       前些天好象有人问过这个问题.
        Use GetModuleFileName 获得应用程序的路径,然后去掉可执行文件名。
          Example:
           TCHAR exeFullPath[MAX_PATH]; // MAX_PATH在API中定义了吧,好象是
128
           GetModuleFileName(NULL,exeFullPath,MAX_PATH)
 
     7. 获得各种目录信息
        Windows目录: Use "GetWindowsDirectory“
        Windows下的system目录: Use "GetSystemDirectory"
        temp目录: Use "GetTempPath "
         当前目录: Use "GetCurrentDirectory"
       请注意前两个函数的第一个参数为目录变量名,后一个为缓冲区; 后两个相
反.
 
     8. 如何自定义消息
        也有人问过的,其实不难。
          (1) 手工定义消息,可以这么写 #define WM_MY_MESSAGE(WM_USER+100),
            MS 推荐的至少是 WM_USER+100;
          (2)写消息处理函数,用 WPARAM,LPARAM返回LRESULT.
             LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)
              {
 
                //加入你的处理函数
              }
           (3) 在类的 AFX_MSG处进行声明,也就是常说的"宏映射"
9-16: 对窗口的控制
 
 9. 如何改变窗口的图标?
    向窗口发送 WM_SECTION消息。
    Example:
      HICON hIcon=AfxGetApp() ->LoadIcon(IDI_ICON);
      ASSERT(hIcon);
      AfxGetMainWnd() ->SendMessage(WM_SECTION,TRUE,(LPARAM) hIcon);
 
10. 如何改变窗口的缺省风格?
      重栽 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);
 
      }
 
 11. 如何将窗口居中显示?
        Easy, 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( );
 
   12. 如何让窗口和 MDI窗口一启动就最大化和最小化?
       先说窗口。
       在 InitStance 函数中设定 m_nCmdShow的取值.
         m_nCmdShow=SW_SHOWMAXMIZED ; //最大化
         m_nCmdShow=SW_SHOWMINMIZED ; //最小化
         m_nCmdShow=SW_SHOWNORMAL   ;   //正常方式
 
        MDI窗口:
          如果是创建新的应用程序,可以用 MFC AppWizard 的Advanced 按钮并在
           MDI子窗口风格组中检测最大化或最小化; 还可以重载 MDI Window 的
            PreCreateWindow函数,设置WS_MAXMIZE or WS_MINMIZE;
         如果从 CMDIChildWnd 派生,调用 OnInitialUpdate函数中的 CWnd::Show
        Window来指定 MDI Child Window的风格。
 
   13. 如何使程序保持极小状态?
       很有意思的问题
        这么办: 在恢复程序窗体大小时, Windows会发送WM_QUERY-OPEN消息,
        用 ClassWizard设置成员函数 OnQueryOpen() ,add following code:
            Bool CMainFrame:: OnQueryOpen( )
              {
                 Return false;
              }
 
   14. 如何限制窗口的大小?
      也就是 FixedDialog形式。 Windows 发送 WM_GETMAXMININFO消息来跟踪,
    响应它,在 OnGetMAXMININFO 中写代码:
 
   15. 如何使窗口不可见?
    很简单,用SW_HIDE 隐藏窗口,可以结合 FindWindow,ShowWindow 控制.
 
   16. 如何使窗口始终在最前方?
      两种途径.
       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);
           }
17、如何创建一个字回绕的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 ;
}
 
18、通用控件的显示窗口
 
    MFC提供了几个CView派生的视窗类,封装了通用控件的功能,但仍然使用工
作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表
控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。
 
19、移动窗口
 
    调用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);
 
20、重置窗口的大小
    调用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 );
21、如何单击除了窗口标题栏以外的区域使窗口移动
 
   当窗口需要确定鼠标位置时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
) )
}
 
22、如何改变视窗的背景颜色
 
    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;
}
 
23、如何改变窗口标题
 
    调用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 );
    }
}
 
24、如何防止主框窗口在其说明中显示活动的文档名
    创建主框窗口和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来设置标题。记住自己设置标题时要遵循接口风格指南。
 
25、如何获取有关窗口正在处理的当前消息的信息
 
    调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用
ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage
来确定所选中的菜单项。
viod CMainFrame : : OnCommmonMenuHandler ( )
{
    //Display selected menu item in debug window .
    TRACE ("Menu item %u was selected . /n" ,
25、如何获取有关窗口正在处理的当前消息的信息
 
    调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用
ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage
来确定所选中的菜单项。
viod CMainFrame : : OnCommmonMenuHandler ( )
{
    //Display selected menu item in debug window .
    TRACE ("Menu item %u was selected . /n" ,
                                 GetCruuentMessage ( ) —> wParam );
}
26、如何创建一个不规则形状的窗口
 
   可以使用新的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 the window .
    UINT nHitTest = CDialog : : OnNcHitTest (point) ;
    rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest ;
    }
27、如何在代码中获取工具条和状态条的指针
 
    缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条
有一个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);
28、如何使能和禁止工具条的工具提示
 
    如果设置了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 );
}
29、如何设置工具条标题
 
    工具条是一个窗口,所以可以在调用CWnd : : SetWindowText来设置标题,
例子如下:
int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct )
{
 
         …
    // Set the caption of the toolbar .
    m_wndToolBar.SetWindowText (_T "Standdard");
30、如何创建和使用无模式对话框
 
    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 ./n") ;
        return ;
    }
 
    //Call DestroyWindow instead of EndDialog .
    DestroyWindow ( ) ;
}
 
void CSampleDialog : : OnCancel ( )
{
    //Call DestroyWindow instead of EndDialog .
    DestroyWindow ( ) ;
}
    其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创
建函数返回后即可删除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) ;
 
    //Create the modeless dialog .
    BOOL bResult = pDialog —> Creste (IDD_IDALOG) ;
    ASSERT (bResult ) ;
}
 
31、如何在对话框中显示一个位图
 
    这要归功于Win 32先进的静态控件和Microsoft的资源编辑器,在对话框中
显示位图是很容易的,只需将图形控件拖到对话中并选择适当属性即可,用户也
可以显示图标、位图以及增强型元文件。
32、如何改变对话或窗体视窗的背景颜色
 
    调用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 );
}
33、如何获取一个对话控件的指针
    有两种方法。其一,调用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 …按钮。如果在对话资源
编辑器中,按下Ctrl键并双击控件即可转到Add Member Variable对话。
34、如何禁止和使能控件
 
    控件也是窗口,所以可以调用CWnd : : EnableWindow使能和禁止控件。
//Disable button controls .
m_wndOK.EnableWindow (FALSE ) ;
m_wndApply.EnableWindow (FALSE ) ;
 
35、如何改变控件的字体
 
    由于控件是也是窗口,用户可以调用CWnd: : SetFont指定新字体。该函数用
一个Cfont指针,要保证在控件撤消之前不能撤消字体对象。下例将下压按钮的字
体改为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 );
 
    …
}
 
36、如何在OLE控件中使用OLE_COLOR数据类型
 
    诸如COleControl : : GetFortColor和COleControl : : GetBackColor等函数
返回OLE _COLOR数据类型的颜色,而GDI对象诸如笔和刷子使用的是COLORREF数据类
型,调用COleControl : : TranslateColor可以很容易地将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 background color .
    pdc—> FilllRect (rcBounds , &brushBack) ;
 
    //other drawign commands
 
    …
 
}
 
37、在不使用通用文件打开对话的情况下如何显示一个文件列表
 
   调用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 ;
}
 
38、为什么旋转按钮控件看起来倒转
 
    需要调用CSpinCtrl : : SetRange 设置旋转按钮控件的范围,旋转按钮控件
的缺省上限为0,缺省下限为100,这意味着增加时旋转按控件的值由100变为0。
下例将旋转按钮控件的范围设置为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旋转按钮控件也有同样的问题:按下Up
按钮时拷贝的数目减少,而按下Down 按钮时拷贝的数目增加。
39为什么旋转按钮控件不能自动地更新它下面的编辑控件
 
    如果使用旋转按钮的autu buddy特性,则必须保证在对话的标记顺序中
buddy窗口优先于旋转按钮控件。从Layout菜单中选择Tab Order菜单项(或者按
下Crtl+D)可以设置对话的标签顺序。
 
40、如何用位图显示下压按钮
 
    Windows 95按钮有几处新的创建风格,尤其是BS_BITMAP和BS_ICON,要想具
有位图按钮,创建按钮和调用CButton : : SetBitmap或CButton : : SetIcon时
要指定BS_BITMAP或BS_ICON风格。
    首先,设置按钮的图标属性。
    然后,当对话初始化时调用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 ;
}
41、如何一个创建三态下压按钮
 
    可以使用新的BS_PUSHBUTTON 风格位和检测框以及按钮来创建一个三态下
压按钮。这很容易,只需将检测框和按钮拖拉到对话中并指定属性Push—like即
可。不用任何附加程序就可以成为三态下压按钮。
 
42、如何动态创建控件
    分配一个控件对象的实例并调用其Create成员函数。开发者最容易忽略两件
事:忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压按
钮控件:
//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 )
 
43、如何限制编辑框中的准许字符
 
    如果用户在编辑控件中只允许接收数字,可以使用一个标准的编辑控件并指
定新的创建标志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 )) ;
}
44、如何改变控件的颜色
 
    有两种方法。其一,可以在父类中指定控件的颜色,或者利用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 ()
}
    现在,控件可以自己决定如何绘画,与父窗口无关。
 
45、当向列表框中添加多个项时如何防止闪烁
 
    调用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 ();
 
46、如何向编辑控件中添加文本
 
    由于没有CEdit:: AppendText函数,用户只好自己做此项工作。调用
CEdit:: SetSel移动到编辑控件末尾,然后调用CEdit:: ReplaceSel添加文
本。下例是AppendText 的一种实现方法:
 
void CMyEdit:: AppendText (LPCSTR pText)
{
     int nLen=GetWindowTextLength ();
     SetFocus ();
     SetSel (nLen, nLen);
 
     ReplaceSel (pText);
}
 
47、如何访问预定义的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);
}
 
48、如何获取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);
}
 
49、如何实现一个橡皮区矩形
 
    CRectTracker是一个很有用的类,可以通过调用CRectTracker::
TrackRubberBand
响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。下例表明使用CRectTracker移动
和重置视窗中的蓝色椭圆的大小是很容易的事情。
    首先,在文件档中声明一个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);
}
 
50、如何更新翻转背景颜色的文本
 
    调用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);
 
}


http://www.niftyadmin.cn/n/1998473.html

相关文章

controller层没有加@responsebody_为什么这段代码没有拦截到 gin String 类型的 response 返回值?...

1. 搬运代码, 高高兴兴gin 是 Golang 中很火的 Web 框架. 最近我有一个拦截 gin response 返回值并记录日志的需求.显然使用 gin 的 middleware 来实现最合适. 我搜索后发现 github 上 gin issue 中有人给出了相关实现,还有好几个赞, 于是乎我就高高兴兴的把代码抄下来了.当时我…

window 编程指南(二)

51、如何创建一个具有特定点大小的字体 可以指定字体逻辑单位的大小&#xff0c;但有时指定字体的点的大小可能会更方便一些。可以如下将字体的点转换为字体的高度&#xff1a; int nHeigthmulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72); 下例创建了一个8点…

Java基础技术细节总结

2019独角兽企业重金招聘Python工程师标准>>> 开发莫忘基础&#xff0c;写业务写多了很多基础内容容易忘。这里将寻根溯源&#xff0c;总结Java语言规范和基础类中的一些细节问题。所有关于Java语言规范的细节问题&#xff0c;都可以参考 The Java Language Specific…

django ajax 更新表格_Python随身听技术精选django精简版与python造火箭

>>>> python随身听&#xff0c;编程任我行 >>>>你好&#xff0c;欢迎回到python随身听&#xff0c;我是主播DE8UG&#xff0c;今天是周一&#xff0c;给你带来的是全球技术精选。我开发的编程入门神器PythonX正在测试中&#xff0c;之前的两期节目和公…

10分钟让你懂得基金是什么

10分钟让你懂得基金是什么 近期见到有很多网友常常提问基金是怎么回事&#xff0c;好象基金是个很复杂难懂的东西&#xff0c;又说推荐去读的基金知识文章看不懂。因此我常想如何让这些朋友在最短的时间内理解基金是什么&#xff0c;为大家展示一下这些并不神秘的基金&#x…

最初的感动:各种应用和代码在BCH这里不断复活

BCH就像是一个孩子&#xff0c;不断的捡起被core扔掉的玩具&#xff0c;并将其仔细擦拭&#xff0c;使玩具变得光彩如新。从零确认技术的重新测试使用到5月份再次分叉将op-return字节数据增加&#xff0c;BCH乐此不疲的恢复一些过去在BTC那里没有获得支持的想法&#xff0c;让这…

celery 停止任务_django - 在Django-Celery中停止/清除定期任务 - SO中文参考 - www.soinside.com...

任务是一条消息&#xff0c;“周期性任务”以周期性间隔发送任务消息。发送的每个任务都将分配有唯一的ID。revoke仅取消单个任务消息。要获取任务的ID&#xff0c;您必须保留跟踪发送的ID&#xff0c;但您也可以在发送任务时指定自定义ID。我不确定您是否要取消单个任务消息&a…

“马俊和黄佳婚姻”所引发的思考

江苏电视台播出的那个有关黄佳和马俊婚姻的节目&#xff0c;大家看了吗 首先声明&#xff1a;我不是针对所有叫黄佳的人。 可我看了&#xff0c;确实觉得那里面的那个黄佳很恶心&#xff0c;下面附上黄佳的博客&#xff1a; 我第一次看到下面的这个帖子&#xff0…