C++学习笔记四

时间:2021-11-03 09:42:39

程序员一定要有好的思维,这样算法才会优良,算法才会巧妙;

 程序员一定要有好的定力,这样遇到问题才会锲而不舍,不骄不躁,问题总会解决的,但不一定是今天,如果

你硬要钻牛角尖的话,能把人给钻哭;但是往往解决问题就在一瞬,要么一个灵感,要么一个偶然的试验;

 

    我初学C++,遇到了很多很多的问题,但是我是一个人独自钻研的,所以其中的艰辛可想而知,但是问题一个一个都得到解决很有一种成功的喜悦和兴奋。因为初学,所以没有经验,C/C++的功底没有学习起来更是无法下手,很多时候甚至不知道如何解决,一点思路都没有,没有办法只有到泡在书店里,搜索引擎,以及MSDN三者相结合了。但是好多时候都是一句代码的事,但是我需要好几天才能解决,这个时候,我解决不了的问题只有暂时放下来,但是我吃饭睡觉回家的路上都在想,还有就是在书店看书的时候总是带着这个问题,很多时候在随便翻书的时候就把这个问题给解决了。初学者唯一不能绕过的路就是多学,多写,多练,多实践。

  前几天,我用VC写了一个从数据库中递归读取分类的程序,无论如何都不能成功,这个时候我就放下了,而且我用了存储过程暂时解决了 我这个问题,后来我调试了调用存储过程的问题的时候,不经意间就在解决这个问题的时候,把那个问题也一并解决了,原因是少了这样一句初始化的代码 m_pRecordSet.CreateInstance(__uuidof(Recordset)); //创建记录集指针,但是我是新手,我不知道啊,多么弱智,还有我在重画我的窗体的时候,我添加了拖动窗口的消息,但是我只要一拖动窗口就会有尾巴,我也无法解决,后来我也是在研究别的问题的时候,突然一想,用框架窗口来响应这个消息应该可以吧,因为最小化,最大化不都是在框架窗口响应的吗,后来就成功了。

 

VC使用技巧:

1. 在任务栏隐藏对话框

    ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);


 

2. 使对话框为顶层窗口

        SetWindowPos(&this->wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);

3. 在运行时添加最大化,最小化按钮

    SetWindowLong(this->m_hWnd, GWL_STYLE,
                  GetWindowLong(this->m_hWnd, GWL_STYLE) |
                  WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
     UpdateWindow();

4. 使能对话框右上角关闭按钮


    在OnInitDialog中

    方法一:
       CMenu* menu = GetSystemMenu(FALSE);
       menu->ModifyMenu(SC_CLOSE, MF_BYCOMMAND | MF_GRAYED );

    方法二:
       CMenu* menu = GetSystemMenu(FALSE);
       menu->EnableMenuItem(SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);

5. 当对话框一部分在屏幕外时,显示全部对话框

    SendMessage(DM_REPOSITION);

6. 改变鼠标外形


    添加 WM_SETCURSOR 消息映射函数

    BOOL CTest6Dlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
    {
         SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HELP));

         return 0;
    }

7. 改变对话框背景色和文本颜色


    在CTest6App的InitInstance中添加

    SetDialogBkColor(RGB(255,0,0), RGB(0,255,0));

10. 在对话框中添加工具栏


    方法一:添加以下代码到 OnInitDialog 中

     if ( !m_wndToolBar.Create(this) || !m_wndToolBar.LoadToolBar(IDR_TOOLBAR1) )
     {
        TRACE0("Failed to Create Dialog Toolbar/n");
        EndDialog(IDCANCEL);
     }

     CRect rcClientOld; // 久客户区RECT
     CRect rcClientNew; // 加入TOOLBAR后的CLIENT RECT
     GetClientRect(rcClientOld); //
     // Called to reposition and resize control bars in the client area of a window
     // The reposQuery FLAG does not really traw the Toolbar. It only does the calculations.
     // And puts the new ClientRect values in rcClientNew so we can do the rest of the Math.
     //重新计算RECT大小
     RepositionBars(AFX_IDW_CONTROLBAR_FIRST,
                       AFX_IDW_CONTROLBAR_LAST,
                       0,
                       reposQuery,
                       rcClientNew);

    // All of the Child Windows (Controls) now need to be moved so the Tollbar does not cover them up.
     //所有的子窗口将被移动,以免被TOOLBAR覆盖
     // Offest to move all child controls after adding Tollbar
     //计算移动的距离
     CPoint ptOffset(rcClientNew.left-rcClientOld.left,
       rcClientNew.top-rcClientOld.top);

     CRect rcChild;
     CWnd* pwndChild = GetWindow(GW_CHILD); //得到子窗口
     while(pwndChild) // 处理所有子窗口
     {
        //移动所有子窗口
         pwndChild->GetWindowRect(rcChild);
        ScreenToClient(rcChild);
        rcChild.OffsetRect(ptOffset);
        pwndChild->MoveWindow(rcChild,FALSE);
        pwndChild = pwndChild->GetNextWindow();
     }

     CRect rcWindow;
     GetWindowRect(rcWindow); // 得到对话框RECT
     rcWindow.right += rcClientOld.Width() - rcClientNew.Width(); // 修改对话框尺寸
     rcWindow.bottom += rcClientOld.Height() - rcClientNew.Height();
     MoveWindow(rcWindow,FALSE); // Redraw Window

     RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);

11.响应对话框的最大化、最小化、关闭、恢复事件


     方法一:添加 WM_SYSCOMMAND 消息映射函数

     void CTest6Dlg::OnSysCommand(UINT nID, LPARAM lParam)
     {
        if ( (nID & 0xFFF0) == IDM_ABOUTBOX )
        {
               CAboutDlg dlgAbout;
               dlgAbout.DoModal();
    }
     else
     {
        if ( nID == SC_MAXIMIZE )
        {
               AfxMessageBox(_T("最大化"));
        }
        else if ( nID == SC_MINIMIZE )
        {
               AfxMessageBox(_T("最小化"));
        }
        else if ( nID == SC_CLOSE )
        {
               AfxMessageBox(_T("关闭"));
        }

        CDialog::OnSysCommand(nID, lParam);
    }

     方法二:添加 WM_SIZE 消息映射函数

     void CTest6Dlg::OnSize(UINT nType, int cx, int cy)
     {
        CDialog::OnSize(nType, cx, cy);

        if ( nType == SIZE_MAXIMIZED )
        {
               AfxMessageBox(_T("最大化"));
        }
        else if ( nType == SIZE_MINIMIZED )
        {
               AfxMessageBox(_T("最小化"));
        }
        else if ( nType == SIZE_RESTORED )
        {
               AfxMessageBox(_T("恢复"));
        }
     }

12.代码实现窗口最小化,最大化,关闭


PostMessage(WM_SYSCOMMAND, SC_MINIMIZE);
PostMessage(WM_SYSCOMMAND, SC_MAXIMIZE);
PostMessage(WM_SYSCOMMAND, SC_CLOSE);

13.按下ESC和ENTER键时禁止关闭对话框

  
    方法一:

     (1) 重载OnCancel和OnOk,屏蔽其中的CDialog::OnCancel()和CDialog::OnOk();
     (2) 添加以下代码
     void CTest6Dlg::OnSysCommand(UINT nID, LPARAM lParam)
     {
         if ((nID & 0xFFF0) == IDM_ABOUTBOX)
          {
             CAboutDlg dlgAbout;   //if you have an about dialog
              dlgAbout.DoModal();
          }
          else if ((nID & 0xFFF0) == SC_CLOSE)
          {
              //用户点击右上角"X"
              EndDialog(IDOK);
      
          }
          else
          {
              CDialog::OnSysCommand(nID, lParam);
          }
     }

    方法二:

     BOOL CTest6Dlg::PreTranslateMessage(MSG* pMsg)
     {
        if ( pMsg->message == WM_KEYDOWN )
        {
               switch(pMsg->wParam)
               {
               case VK_ESCAPE:
                return TRUE; //直接返回TRUE
                break;
               case VK_RETURN:
                return TRUE;
                break;
               }
        }
        return CDialog::PreTranslateMessage(pMsg);
     }

     方法三:
         Q122489:
         How to Disable Default Pushbutton Handling for MFC Dialog
         http://support.microsoft.com/kb/122489/en-us

14.在对话框中处理键盘鼠标消息


处理PreTranslateMessage消息

以下代码示例只演示了键盘WM_KEYDOWN消息,你也可以处理鼠标消息,比如WM_LBUTTONDOWN,WM_LBUTTONUP,WM_RBUTTONDOWN等。

BOOL CTest6Dlg::PreTranslateMessage(MSG* pMsg)
{
    /**********************************************************/
    /*    当焦点在combobox(drop down风格)的edit上,响应回车            */
    /***********************************************************/
    if ( pMsg->message == WM_KEYDOWN )
    {        
        switch( pMsg->wParam )
        {
        case VK_RETURN:
            CEdit *pEdit = (CEdit*)m_combo1.GetWindow(GW_CHILD);
            if(pMsg->hwnd == pEdit->m_hWnd )
            {
  

AfxMessageBox("在combobox的edit中按下了Enter!");
            }           
            return TRUE;
        }
    }

    /****************************************/
    /*  
ALT为WM_SYSKEYDOWN                  */
    /****************************************/

    if( pMsg->message == WM_SYSKEYDOWN )
    {   
        switch( pMsg->wParam )
        {
        case VK_F1:   
            if(::GetKeyState(VK_MENU) < 0)//ALT+F1
            {
                AfxMessageBox("按下了ALT+F1");
                return TRUE;
            }           
        }       
    }
  
    /****************************************/
    /*     在clistctrl中按ctrl+A选中所有项 */
    /****************************************/
    if( pMsg->message == WM_KEYDOWN )
    {   
        if(pMsg->hwnd == GetDlgItem(IDC_LIST1)->m_hWnd)
        {
            switch( pMsg->wParam )
            {
            case 65://A   
            if(::GetKeyState(VK_CONTROL) < 0)//Shift+enter
            {
                    for(int i=0; i

15.对话框启动即隐藏


    添加 WM_SHOWWINDOW 的消息映射

     void CTest6Dlg::OnShowWindow(BOOL bShow, UINT nStatus)
     {
        if ( GetStyle() & WS_VISIBLE )
        {
               CDialog::OnShowWindow(bShow, nStatus);
        }
        else
        {
               long Style = ::GetWindowLong(*this, GWL_STYLE);
               ::SetWindowLong(*this, GWL_STYLE, Style | WS_VISIBLE);
               CDialog::OnShowWindow(SW_HIDE, nStatus);
        }
     }

16.对话框自动停靠在屏幕边


    const int DETASTEP = 50;
     BOOL AdjustPos(CWnd *pWnd, CRect* lpRect)
     {
        //自动靠边
        int iSX = GetSystemMetrics(SM_CXFULLSCREEN);
        int iSY = GetSystemMetrics(SM_CYFULLSCREEN);
        RECT rWorkArea;
        BOOL bResult = SystemParametersInfo(SPI_GETWORKAREA, sizeof(RECT), &rWorkArea, 0);

        CRect rcWA;
        if ( !bResult )
        {
            //如果调用不成功就利用GetSystemMetrics获取屏幕面积
            rcWA = CRect(0,0,iSX,iSY);
        }
        else
            rcWA = rWorkArea;

        int iX = lpRect->left;
        int iY = lpRect->top;
        if ( iX < rcWA.left + DETASTEP && iX!=rcWA.left )
        {
            //调整左
            pWnd->SetWindowPos(NULL,rcWA.left,iY,0,0,SWP_NOSIZE);
            lpRect->OffsetRect(rcWA.left-iX,0);
            AdjustPos(lpRect);
            return TRUE;
        }
        if ( iY < rcWA.top + DETASTEP && iY!=rcWA.top )
        {
            //调整上
            pWnd->SetWindowPos(NULL ,iX,rcWA.top,0,0,SWP_NOSIZE);
            lpRect->OffsetRect(0,rcWA.top-iY);
            AdjustPos(lpRect);
            return TRUE;
        }
        if ( iX + lpRect->Width() > rcWA.right - DETASTEP && iX !=rcWA.right-lpRect->Width() )
        {
            //调整右
            pWnd->SetWindowPos(NULL ,rcWA.right-rcW.Width(),iY,0,0,SWP_NOSIZE);
            lpRect->OffsetRect(rcWA.right-lpRect->right,0);
            AdjustPos(lpRect);
            return TRUE;
        }
        if ( iY + lpRect->Height() > rcWA.bottom - DETASTEP && iY !=rcWA.bottom-lpRect->Height() )
        {
            //调整下
            pWnd->SetWindowPos(NULL ,iX,rcWA.bottom-rcW.Height(),0,0,SWP_NOSIZE);
            lpRect->OffsetRect(0,rcWA.bottom-lpRect->bottom);
            return TRUE;
        }
        return FALSE;
    }

    //然后在ONMOVEING事件中使用如下过程调用
    CRect r=*pRect;
    AdjustPos(this, &r);
    *pRect=(RECT)r;

17.单击窗口任意位置都可拖动窗口

    方法一:
     添加 WM_LBUTTONDOWN 的消息映射
     void CTest6Dlg::OnLButtonDown(UINT nFlags, CPoint point)
     {
        PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0);

        CDialog::OnLButtonDown(nFlags, point);
     }

    方法二:
   
添加 WM_NCHITTEST 的消息映射
    注意:在classwizard->message中找不到
WM_NCHITTEST的,需要在选项卡class info->message filter中选择window后该消息才会出现在message中。
     void CTest6Dlg::OnNCHitTest(CPoint point)
     {
            return HTCAPTION;
    //    return CDialog::
OnNCHitTest(point);
     }

     或者参考
        http://msdn.microsoft.com/msdnmag/issues/02/12/CQA/default.aspx

18.用Enter键替换Tab键实现焦点切换


     BOOL CTest6Dlg::PreTranslateMessage(MSG* pMsg)
     {
        if ( pMsg->message == WM_KEYDOWN )
          {
              if ( pMsg->wParam == VK_RETURN )
                   pMsg->wParam = VK_TAB;
          }
          return CDialog::PreTranslateMessage(pMsg);
     }

19.在对话框添加快捷键


     (1) 在CXXXApp中类中添加声明
        HACCEL m_haccel;
     (2) 在resource view中右键点击树的根目录,选择insert,添加一个新的Accelerator,默认ID为IDR_ACCELERATOR1。
         在其中添加相应菜单的快捷键。
     (3) 在BOOL CXXXApp::InitInstance()中添加代码
        m_haccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));
     (4) 添加CXXXApp类的 ProcessMessageFilter 消息映射函数
         BOOL CTest6App::ProcessMessageFilter(int code, LPMSG lpMsg)
         {
              if ( m_haccel )
              {
                  if ( ::TranslateAccelerator(m_pMainWnd->m_hWnd, m_haccel, lpMsg) )
                       return TRUE;
              }
              return CWinApp::ProcessMessageFilter(code, lpMsg);
         }

或者参考
Q100770:
How to use accelerator keys and a main menu on the dialog box in Visual C++
http://support.microsoft.com/kb/100770/en-us

Adding Hot Keys to your Application
http://msdn.microsoft.com/msdnmag/issues/1200/c/default.aspx

20.对话框全屏


    int cx, cy;
    HDC dc = ::GetDC(NULL);
    cx = GetDeviceCaps(dc,HORZRES) + GetSystemMetrics(SM_CXBORDER);
    cy = GetDeviceCaps(dc,VERTRES) + GetSystemMetrics(SM_CYBORDER);
    ::ReleaseDC(0,dc);

    // Remove caption and border
    SetWindowLong(m_hWnd, GWL_STYLE,
                    GetWindowLong(m_hWnd, GWL_STYLE) & (~(WS_CAPTION | WS_BORDER)));

    // Put window on top and expand it to fill screen
    ::SetWindowPos(m_hWnd, HWND_TOPMOST,
          -(GetSystemMetrics(SM_CXBORDER)+1),
          -(GetSystemMetrics(SM_CYBORDER)+1),
          cx+1,cy+1, SWP_NOZORDER);
    或参考
        http://www.codeguru.com/cpp/w-d/dislog/dialog-basedapplications/article.php/c1837/

 

 

 

 

http://www.joyvc.cn/GuiAndWindows/GuiAndWindows00040.html

一、简单对话框全屏显示方法
        在OnInitDialog()中任意加入:
        1、ModifyStyle(WS_CAPTION,0,0);  //如果不想去掉标题栏,去掉该句。
                SendMessage(WM_SYSCOMMAND,SC_MAXIMIZE,0);
        2、ShowWindow(SW_SHOWMAXIMIZED); 
        二、复杂一点的对话框全屏显示方法,随屏幕的分辩率而调节
        void CMainFrame::OnFullScreen()   
        {
                GetWindowPlacement(&m_OldWndPlacement);   
                CRect WindowRect;   
                GetWindowRect(&WindowRect);   
                CRect ClientRect;   
                RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &ClientRect);   
                ClientToScreen(&ClientRect);
   
                //获取屏幕的分辨率   
                int nFullWidth=GetSystemMetrics(SM_CXSCREEN);   
                int nFullHeight=GetSystemMetrics(SM_CYSCREEN);
   
                //将除控制条外的客户区全屏显示到从(0,0)到(nFullWidth, nFullHeight)区域,
                //将(0,0)和(nFullWidth, nFullHeight)两个点外扩充原窗口和除控制条之外的
                //客户区位置间的差值, 就得到全屏显示的窗口位置   
                m_FullScreenRect.left=WindowRect.left-ClientRect.left;   
                m_FullScreenRect.top=WindowRect.top-ClientRect.top;   
                m_FullScreenRect.right=WindowRect.right-ClientRect.right+nFullWidth;   
                m_FullScreenRect.bottom=WindowRect.bottom-ClientRect.bottom+nFullHeight;   
                m_bFullScreen=TRUE;  //设置全屏显示标志为TRUE
   
                //进入全屏显示状态   
                WINDOWPLACEMENT wndpl;   
                wndpl.length=sizeof(WINDOWPLACEMENT);   
                wndpl.flags=0;   
                wndpl.showCmd=SW_SHOWNORMAL;   
                wndpl.rcNormalPosition=m_FullScreenRect;   
                SetWindowPlacement(&wndpl);
        }

        三、对话框全屏及按钮控件移到相应位置
        void CXXXDlg::OnLButtonDown(UINT nFlags, CPoint point)   
        {                   
                int cx=::GetSystemMetrics(SM_CXSCREEN); 
                int cy=::GetSystemMetrics(SM_CYSCREEN); 
   
                CRect rtClient,rtBtn; 
                CWnd  *pWnd=GetDlgItem(IDC_BUTTON); 
   
                GetClientRect(&rtClient);            //获得对话框客户区屏幕坐标 
                ClientToScreen(&rtClient);            //映射为屏幕坐标 
                pWnd->GetWindowRect(&rtBtn);          //获得button屏幕坐标 
 
                int lx=rtBtn.Width();                //button长度 
                int ly=rtBtn.Height();                //button高度 
                int dx=rtClient.right-rtBtn.right;    //离右边框的距离 
                int dy=rtClient.bottom-rtBtn.bottom;  //离底边框的距离 
 
                MoveWindow(CRect(0,0,cx,cy));                            //移动窗口 
                pWnd->MoveWindow(CRect(cx-dx-lx,cy-ly-dy,cx-dx,cy-dy));  //移动button 
 
                CDialog::OnLButtonDown(nFlags, point); 
        }

        四、设计状态下指定对话框以全屏显示
        1、手工把它拽成比如1024×768, 然后Alt+V  U
        2、在*.rc文件中修改,但是单位不一样。

        五、用MoveWindow或SetWindowPos全屏对话框
        首先计算出客户区的大小GetClientRect();
        再计算出整个窗口的大小GetWindowRect();
        然后再得到当前屏幕的大小GetSystemMetrics();
        最后根据这三个数据进行换算,当客户区为屏幕大小时窗口的位置的大小;
        计算完成后调用MoveWindow就可以了。


发消息的时候传递任意复杂的类型:

like   this  
  struct  
  {  
  char   df[1024];  
  int   d;  
  long   lk;  
  a*     pa;  
  }test;  
  test*   pt=new   test;  
  sendmessage(m_hwnd,WM_XXX,pt,0);  

 

用结构体,类都可以完成你的要求,想传多少都可以的.  
  比如:  
  class   A{  
  public:    
          int   nPara;  
          CString   strPara;  
          float   fPara;  
          BOOL     bPara;  
  }  
  A   *   pt=new   A;  
  A->nPara   =   1;//init   your   para.  
  sendmessage(m_hwnd,WM_XXX,p,0);  
   
   
  在消息处理函数中,直接对p强制类型转化为A类,即可使用  
  A   *p1   =   (A   *)   lpram;

在子窗口关闭的时候给父窗口发消息:

       CWnd* pWnd = CWnd::FromHandle(m_hWnd);
       ::PostMessage(pWnd->GetParent()->GetSafeHwnd(),nMsg,wParam,lParam);

 

点击隐藏显示ListCtrl列:
  static b = TRUE;
 b = !b;
 m_list.SetColumnHide(1, b);

 

对话框上建立View的方法

OnInitDialog()
{
  CDialog:;OnInitDialog();

CRect rectWindows;
GetWinodwRect(&rectWindows);
CRuntimeClass *pViewClass=RUNTIME_CLASS(CXXXView);
CCreateContext *pContext=new CCreateContext;
pContext->m_pCurrentDoc=NULL;
pContext->m_pCurrentFrame=NULL;
pContext->m_pLastView=NULL;
pContext->m_pNewDocTemplate=NULL;
pContext->m_pNewViewClass=pViewClass;

CWnd *pWnd=DYNAMIC_DOWNCAST(CWnd,pviewClass->CreateObject());
pWnd->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0),this,pContext);
delete pContext;
CXXXView *pView=DYUNAMIC_DOWNCAST(CXXXView,pWnd);
...............
}

 

 

SetWindowLong(m_hWnd,   GWL_USERDATA,   (LONG)this);  这个语句把这个对象的地址保存在窗口结构的用户自定义数据成员里。

把日期转换成字符串输出:

   CTime   time=CTime::GetCurrentTime();  
    CString   display;  
    display.Format(_T("%04d-%02d-%02d   %02d:%02d:%02d"),    
                                time.GetYear(),  
                                time.GetMonth(),  
                                time.GetDay(),  
                                time.GetHour(),    
                                time.GetMinute(),  
                                time.GetSecond());

<?XML:NAMESPACE PREFIX = O />