新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → VC编程常用捷径 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 6853 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: VC编程常用捷径 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     一分之千 帅哥哟,离线,有人找我吗?射手座1984-11-30
      
      
      威望:1
      等级:研一(随老板参加了WWW大会还和Tim Berners-Lee合了影^_^)
      文章:632
      积分:4379
      门派:XML.ORG.CN
      注册:2006/12/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给一分之千发送一个短消息 把一分之千加入好友 查看一分之千的个人资料 搜索一分之千在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看一分之千的博客楼主
    发贴心情 VC编程常用捷径

    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处进行声明,也就是常说的"宏映射"


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    越学越无知

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/7/18 11:02:00
     
     一分之千 帅哥哟,离线,有人找我吗?射手座1984-11-30
      
      
      威望:1
      等级:研一(随老板参加了WWW大会还和Tim Berners-Lee合了影^_^)
      文章:632
      积分:4379
      门派:XML.ORG.CN
      注册:2006/12/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给一分之千发送一个短消息 把一分之千加入好友 查看一分之千的个人资料 搜索一分之千在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看一分之千的博客2
    发贴心情 
    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);
               }

    ----------------------------------------------
    越学越无知

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/7/18 11:04:00
     
     一分之千 帅哥哟,离线,有人找我吗?射手座1984-11-30
      
      
      威望:1
      等级:研一(随老板参加了WWW大会还和Tim Berners-Lee合了影^_^)
      文章:632
      积分:4379
      门派:XML.ORG.CN
      注册:2006/12/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给一分之千发送一个短消息 把一分之千加入好友 查看一分之千的个人资料 搜索一分之千在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看一分之千的博客3
    发贴心情 
    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 , point );
                                                                                  
      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)     

    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: : 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" ,
                                     GetCruuentMessage ( ) —> wParam );
    }

    ----------------------------------------------
    越学越无知

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/7/18 11:06:00
     
     一分之千 帅哥哟,离线,有人找我吗?射手座1984-11-30
      
      
      威望:1
      等级:研一(随老板参加了WWW大会还和Tim Berners-Lee合了影^_^)
      文章:632
      积分:4379
      门派:XML.ORG.CN
      注册:2006/12/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给一分之千发送一个短消息 把一分之千加入好友 查看一分之千的个人资料 搜索一分之千在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看一分之千的博客4
    发贴心情 
    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 (
    )
    );

        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  ( )
    {
                                                                                  
        // 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 ) ;
    }

    ----------------------------------------------
    越学越无知

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/7/18 11:07:00
     
     一分之千 帅哥哟,离线,有人找我吗?射手座1984-11-30
      
      
      威望:1
      等级:研一(随老板参加了WWW大会还和Tim Berners-Lee合了影^_^)
      文章:632
      积分:4379
      门派:XML.ORG.CN
      注册:2006/12/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给一分之千发送一个短消息 把一分之千加入好友 查看一分之千的个人资料 搜索一分之千在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看一分之千的博客5
    发贴心情 
    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 : : GetBacalog : : 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  ( )
    {
                                                                                  
        // 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 ) ;
    }
    37、如何访问桌面窗口
        静态函数CWnd:: GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC
    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);
         }

    38、如何确定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\n", szDir);
    //Get the full path of the windows system directory.
    :: GetSystemDirectory (szDir, MAX_PATH);
    :: GetSystemDirectory (szDir, MAX_PATH);
        调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径
    检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。
    下例说明了如何创建一个临时文件。

         //get unique temporary file.
         CString strFile;
         TRY
         {
            //Create file and write data.Note that file is closed
            //in the destructor of the CFile object.
            //write data
         CATCH (CFileException, e)
         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);
         //Create a unique temporary file.
         TCHAR szTempFile  [MAX_PATH];
         UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile);
         strTempName=szTempFile;
    }
    39.如何检索原先的Task Manager应用程序使用的任务列表
       原先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口
    必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: GetWindow可以
    检索顶层窗口的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwner
    void GetTadkList (CListBox&list)
    {
         //Get first Window in window list.
         ASSERT_VALID (AfxGetMainWnd ());
         //Walk window list.
         while (pWnd)
         {
             // I window visible, has a caption, and does not have an owner?
             if (pWnd ->IsWindowVisible () &&
             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);
         }
    40.如何使用一个预定义的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);
        调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如
    //Initialize CSize object with screen size.
    CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN))

    ----------------------------------------------
    越学越无知

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/7/18 11:10:00
     
     一分之千 帅哥哟,离线,有人找我吗?射手座1984-11-30
      
      
      威望:1
      等级:研一(随老板参加了WWW大会还和Tim Berners-Lee合了影^_^)
      文章:632
      积分:4379
      门派:XML.ORG.CN
      注册:2006/12/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给一分之千发送一个短消息 把一分之千加入好友 查看一分之千的个人资料 搜索一分之千在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看一分之千的博客6
    发贴心情 
    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_PUSHBUTTO
    N
    .

    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);

    }

                                                                
    51、如何创建一个具有特定点大小的字体

        可以指定字体逻辑单位的大小,但有时指定字体的点的大小可能会更方便一
    些。可以如下将字体的点转换为字体的高度:

    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"));

    ...
    52、如何计算一个串的大小
                                                                                   
        函数CDC:: Det text Extent 根据当前选择的字体计算一个串的高度和宽
    度。如果使用的不是系统字体而是其他字体,则在调用GetTextExtent之前将字
    体选进设备上下文中是很重要的,否则计算高度和宽度时将依据系统字体,由此
    得出的结果当然是不正确的。下述样板程序当改变下压按钮的标题时动态调整按
    钮的大小,按钮的大小由按钮的字体和标题的大小而定。响应消息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;
    }

    53、如何显示旋转文本

        只要用户使用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 ();
         }
    }

    54、如何正确显示包含标签字符的串

        调用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\tNorman\tOliver"));
         int nTabStop=20; //tabs are every 20 pixels
         pDC->TabbedtextOut (10, 10, str, 1, &nTabStop, 10);
    }

    55、串太长时如何在其末尾显示一个省略号

        调用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);
    }

    56、如何快速地格式化一个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);

    57、为什么即使调用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);

    58、如何给系统菜单添加一个菜单项

        给系统菜单添加一个菜单项需要进行下述三个步骤:
        首先,使用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的串表的入口来实现。

    59、如何确定顶层菜单所占据的菜单行数

        这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高
    度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;
        最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代
    码实现。

    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);
    }

    60、在用户环境中如何确定系统显示元素的颜色

        调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。下例说明了如何
    在MFC函数CMainFrameWnd:: OnNcPaint中调用该函数设置窗口标题颜色。

    void CMiniFrameWnd:: OnNcPaint ()
    {
         …
                         CRect rcFrame,rcClient;
         GetWindowRect (rcFrame);
         GetClientRect (rcClient);
         return (rcFrame.Height () -rcClient.Height ()-
               :: GetSystemMetrics (SM_CYCAPTION) -
               (:: getSystemMetrics (SM_CYFRAME) *2)) /
               :: GetSystemMetrics (SM_CYMENU);
    }

    60、在用户环境中如何确定系统显示元素的颜色

        调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。下例说明了如何
    在MFC函数CMainFrameWnd:: OnNcPaint中调用该函数设置窗口标题颜色。

    void CMiniFrameWnd:: OnNcPaint ()
    {
         dc.SetTextColor (:: GetSysColor (m_bActive ?
             COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
         …
    }

                                                
    61、如何查询和设置系统参数

        在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);

    62、如何使用一个预定义的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);
    }

    63、如何确定当前屏幕分辨率

        调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如
    标题大小、边界大小以及滚动条大小等等。

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

    64、如何检索原先的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);
         }
    }

    65、如何确定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\n", szDir);
    //Get the full path of the windows system directory.
    :: GetSystemDirectory (szDir, MAX_PATH);
    TRACE ("Windows system directory %s\n", szDir);

    66、在哪儿创建临文件

        调用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;
    }

    67、如何访问桌面窗口
           
        静态函数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);
         }
                                                                                   
         
         //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);
         }
    }
       …

    68. 怎样把内存释放干净

         C语言的一个好的特性也是坏的特性是它有一个指针类型.由于指针的存在,一些

    小的编程失误常会导致内存释放得不干净,或者同一个地址释放两次.ANSI C的模块特

    性不如C++强,因此在ANSI C中比C++更容易产生这样的问题.对ANSI C的解决方法就是

    加强其模块的内聚度,减少模块间的耦合度,使得指针的应用限制在模块内或一些特殊

    的接口上,将它的可维护性向C++靠拢.

         根据C++的结构特性,它的指针使用具有很多规律可循.看下面的一个例子:

    class CTestDialog: public CDialog {

        private:

            CMyRecordSet *m_table;

        public:

            CTestDialog();

            ~CTestDialog();

            InitialDialog();

            OnOk();

        1.在CTestDialog中应该作 m_table=NULL;ialogalDialog

        2.在InitalDialog里作    ASSERT(m_table==NULL);m_table=new CMyRecordSet;

        3.在OnOk里作            m_table->Update();

        4.在~CTestDialog中作    if(m_table){delete m_table;m_table=NULL;}

        第1步的目的是防止在4步中delete一个并未初始化的指针(因为可能初始化不成功

    而不调InitialDialog反而调~CTestDialog,但显然m_table并没有初始化:这里有一个

    问题是用惯了UNIX的用户以为m_table是NULL,实际上WIN里面根本没有这个置初值的

    习惯,即使有这个约定,我们难到能保证到另一个操作系统,另一套C++中还是如此约定?)

        第2步只是既于可能要显示m_table中的数据,在这时作初始化可能比较好,当然也

    可以放到CTestDialog中,只要能运行正常.

        第3步是一个标准操作而已.

        第4步释放内存.判m_table为NULL是避免没有InitalDialog成功,也是为了防止

    二次释放.m_table=NULL在~CTestDialog中显得不是很有意义.如果释放操作移到OnOk里就有作用了.

    这个例子只说明了在使用指针的过程中要注意的几个问题

        注意指针的初值,最好是在初始化类时就附上.

        在类的生存期即将结束时,注意将其包含的指针逐个判别释放.

        比较容易想到的是在给指针重新附有效值时,最好要加一句 ASSERT(m_table==NULL);

    这样不会丢失内存.(条件是在delete m_table后立即执行m_table=NULL)

        这里主要讲的是全局指针问题.对于函数内的指针,只要细心,入口处new,

    出口处delete,不会有什么内存的问题;唯一比较难缠的是一些比较复杂的数据结构

    操作,指针附过来附过去,也就没有什么好的规律可言,全靠技术了.

    ----------------------------------------------
    越学越无知

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/7/18 11:12:00
     
     GoogleAdSense射手座1984-11-30
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/23 1:24:37

    本主题贴数6,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    296.875ms