zoukankan      html  css  js  c++  java
  • 精通 VC++ 实效编程280例

    窗口是屏幕上的一个矩形区域。窗口分为3种:重叠窗口、弹出窗口和子窗口。每个窗口都有由系统绘制的“非客户区”和应用程序绘制的“客户区”。在 MFC 中,CWnd 类为各种窗口提供了基类。

    1 通过 HWND 获得 CWnd 指针

    通过 HWND 获得 Cwnd 指针可以调用 Cwnd::FromHandle 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    void CDemoDlg::OnButton1()
    {
        HWND hWnd = GetSafeHwnd();  //获得当前窗口的句柄
        CWnd* pWnd = CWnd::FromHandle(hWnd);    //通过HWND获得CWnd指针
        CString strText = _T("");
        strText.Format("pWnd=0x%X this=0x%X ",pWnd,this);
        AfxMessageBox(strText);
    }

    2 获得应用程序主窗口的指针

    主窗口指针保存在 CWinThread::m_pMainWnd 中。可以首先调用 AfxGetApp 函数获得应用程序的指针,然后通过应用程序指针获得主窗口的指针。

    1
    2
    3
    4
    5
    6
    7
    8
    void CDemoDlg::OnButton2()
    {
        CDemoApp* pApp = (CDemoApp*)AfxGetApp();    //获得应用程序指针
        CWnd* pMainWnd = pApp->m_pMainWnd;   //获得主窗口指针
        CString strText = _T("");
        strText.Format("pMainWnd=0x%X this=0x%X ",pMainWnd,this);
        AfxMessageBox(strText);
    }

    3 获得指定点的窗口

    获得指定点的窗口可以调用 CWnd::WindowFromPoint 函数。

    a 在 CDemoDlg 类中重载 CWnd::PreTranslateMessage 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    BOOL CDemoDlg::PreTranslateMessage(MSG* pMsg)
    {
        if (pMsg->message == WM_MOUSEMOVE)
        {
            CPoint point(LOWORD(pMsg->lParam),HIWORD(pMsg->lParam));
            ::ClientToScreen(pMsg->hwnd, &point);    //客户区坐标转换为屏幕坐标
            OnMouseMove(0,point);
        }
        return CDialog::PreTranslateMessage(pMsg);
    }

    b 在 CDemoDlg 类中添加 WM_MOUSEMOVE 消息处理函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    void CDemoDlg::OnMouseMove(UINT nFlags, CPoint point)
    {
        CWnd* pWnd = WindowFromPoint(point);    //获得指定点的窗口
        if (pWnd != NULL)
        {
            TRACE("%d ",pWnd);
            if (IsChild(pWnd))
            {
                CString strText = _T("");
                pWnd->GetWindowText(strText);
                SetWindowText(strText);
            }
        }
        CDialog::OnMouseMove(nFlags, point);
    }

    4 最大化和最小化窗口

    最大化和最小化窗口可以调用 CWnd::SendMessage 函数发送最大化或最小化窗口消息。

    LRESULT SendMessage( 

    UINT message,    //发送的消息,值为 WM_SYSCOMMAND 时表示系统命令消息。 

    WPARAM wParam = 0,     //当 message 值为 WM_SYSCMMAND,参数 wParam 值为 SC_MAXIMIZE、SC_MINIMIZE、

    LPARAM lParam = 0 );      //SC_RESTORE 时分别表示最大化窗口、最小化窗口、恢复窗口。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    void CDemoDlg::OnButton3()
    {
        //最大化窗口
        SendMessage(WM_SYSCOMMAND,SC_MAXIMIZE,0);
    }
     
    void CDemoDlg::OnButton4()
    {
        //最小化窗口
        SendMessage(WM_SYSCOMMAND,SC_MINIMIZE,0);
    }
     
    void CDemoDlg::OnButton5()
    {
        //恢复窗口
        SendMessage(WM_SYSCOMMAND,SC_RESTORE,0);
    }

    5 关闭窗口

    关闭窗口可以调用 CWnd::SendMessage 函数发送 WM_CLOSE 消息。框架将调用 CWnd::OnClose 函数处理 WM_CLOSE 消息。默认情况下,OnClose 函数将调用 CWnd::DestroyWindow 函数关闭窗口。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void CDemoDlg::OnButton6()
    {
        //关闭窗口
        SendMessage(WM_CLOSE,0,0);
    }
     
    void CDemoDlg::OnClose() //添加 WM_CLOSE 消息处理函数
    {
        //判断是否关闭
        if (IDYES == MessageBox(_T("是否关闭窗口?"),NULL,MB_YESNO))
        {
            CDialog::OnClose();
        }
    }

    6 设置窗口的大小和位置

    设置窗口大小和位置可通过两种方法:1.调用 CWnd::SetWindowPos 函数;2.调用 CWnd::MoveWindow 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void CDemoDlg::OnButton7()
    {
        //设置窗口的大小和位置
        SetWindowPos(NULL,0,0,320,200,SWP_NOZORDER);
    }
     
    void CDemoDlg::OnButton8()
    {
        //设置窗口的大小和位置
        MoveWindow(0,200,200,320);
    } 

    7 居中显示窗口

    使窗口居中显示可以调用 CWnd::CenterWindow 函数。

    1
    2
    3
    4
    5
    void CDemoDlg::OnButton9()
    {
        //居中显示窗口
        CenterWindow();
    } 

    8 顶层显示窗口

    使窗口顶层显示,可以调用 CWnd::SetWindowPos 函数,设置对话框窗口的层次为最顶层。

    1
    2
    3
    4
    5
    void CDemoDlg::OnButton10()
    {
        //设置窗口层次
        SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE);  //SWP_NOSIZE:表示窗口保持当前的大小,SWP_NOMOVE:表示窗口保持当前的位置
    }

    9 设置窗口图标

    首先调用 CWinApp::LoadIcon 函数加载图标资源,然后调用 CWnd::SetIcon 函数设置图标。

    1
    2
    3
    4
    5
    6
    7
    void CDemoDlg::OnButton11()
    {
        //加载图标
        HICON hIcon = AfxGetApp()->LoadIcon(IDI_ICON);
        //设置图标
        SetIcon(hIcon,FALSE);   //FALSE:设置程序小图标,TRUE:设置任务栏大图标
    } 

    10 获得和设置窗口的标题

    获得和设置窗口标题可以分别调用 CWnd::GetWindowText 和 CWnd::SetWindowText 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void CDemoDlg::OnButton12()
    {
        CString strText = _T("");
        GetWindowText(strText);             //获得窗口标题
        SetDlgItemText(IDC_TEXT,strText);   //设置编辑框文本
    }
     
    void CDemoDlg::OnButton13()
    {
        CString strText = _T("");
        GetDlgItemText(IDC_TEXT,strText);   //获得编辑框文本
        SetWindowText(strText);             //设置窗口标题
    }

    11 显示或隐藏窗口的标题栏

    显示或隐藏窗口的标题栏可以调用 CWnd::ModifyStyle 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void CDemoDlg::OnButton14()
    {
        //删除标题栏风格
        ModifyStyle(WS_CAPTION,0,SWP_FRAMECHANGED);
    }
     
    void CDemoDlg::OnButton15()
    {
        //添加标题栏风格
        ModifyStyle(0,WS_CAPTION,SWP_FRAMECHANGED);
    }

    12 改变窗口形状

    标准窗口的形状是矩形的。改变窗口的形状首先调用 CRgn 类的成员函数创建相应形状的区域,然后调用 CWnd::SetWindowRgn 函数将其设置为窗口区域。

    CRgn 类的 CreateRectRgn、CreateEllipticRgn、CreatePolygonRgn 和 CreateRoundRectRgn 函数可以分别用来创建矩形、椭圆形、多边形和圆矩形区域。 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    void CDemoDlg::OnButton16()
    {
        CRect rect;
        GetClientRect(rect);
        //创建矩形区域
        CRgn rgn;
        rgn.CreateRectRgn(rect.left,rect.top,rect.right,rect.bottom);
        //设置窗口的区域
        SetWindowRgn((HRGN)rgn,TRUE);
    }
     
    void CDemoDlg::OnButton17()
    {
        CRect rect;
        GetClientRect(rect);
        //创建椭圆形区域
        CRgn rgn;
        rgn.CreateEllipticRgn(0,0,rect.Width(),rect.Height());
        //设置窗口的区域
        SetWindowRgn((HRGN)rgn,TRUE);
    }
     
    void CDemoDlg::OnButton18()
    {
        CRect rect;
        GetClientRect(rect);
        CPoint point[6];
        point[0].x = 0;
        point[0].y = rect.Height() / 2;
        point[1].x = rect.Width() / 3;
        point[1].y = 0;
        point[2].x = 2 * rect.Width() / 3;
        point[2].y = 0;
        point[3].x = rect.Width();
        point[3].y = rect.Height() / 2;
        point[4].x = 2 * rect.Width() / 3;
        point[4].y = rect.Height();
        point[5].x = rect.Width() / 3;
        point[5].y = rect.Height();
        //创建多边形区域
        CRgn rgn;
        rgn.CreatePolygonRgn(point,6,ALTERNATE);
        //设置窗口的区域
        SetWindowRgn((HRGN)rgn,TRUE);
    }
     
    void CDemoDlg::OnButton19()
    {
        CRect rect;
        GetClientRect(rect);
        //创建圆矩形区域
        CRgn rgn;
        rgn.CreateRoundRectRgn(0,0,rect.Width(),rect.Height(),rect.Width() / 2,rect.Height() / 2);
        //设置窗口的区域
        SetWindowRgn((HRGN)rgn,TRUE);
    }

    13 设置窗口的透明区域

    设置窗口的透明区域,首先调用 CRgn::CreateRectRgn 创建一个区域,然后调用 CRgn::CombineRgn 函数将需要透明的区域去掉,最后调用 CWnd::SetWindowRgn 函数将其设置为窗口区域。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    void CDemoDlg::OnButton20()
    {
        CRect rect1;
        GetWindowRect(rect1);
        CRect rect2;
        GetClientRect(rect2);
        ClientToScreen(rect2);
        CRgn rgn1;
        rgn1.CreateRectRgn(rect1.left,rect1.top,rect1.right,rect1.bottom);
        CRgn rgn2;
        rgn2.CreateRectRgn(rect2.left,rect2.top,rect2.right,rect2.bottom);
        CRgn rgn;
        rgn.CreateRectRgn(0,0,1,1);
        rgn.CombineRgn(&rgn1,&rgn2,RGN_DIFF);
        //设置窗口区域
        SetWindowRgn((HRGN)rgn,TRUE);
    }

    14 透明窗口

    实现透明窗口,首先调用 CWnd::ModifyStyleEx 函数,添加窗口的 WS_EX_LAYERED(0x00080000) 扩展风格,然后调用 SDK 的 SetLayeredWindowAttributes 函数设置窗口的透明度和透明色。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    void CDemoDlg::OnButton21()
    {
        //添加 WS_EX_LAYERED(0x80000) 扩展风格
        ModifyStyleEx(0,0x80000);
        //加载 User32.DLL 动态链接库
        HMODULE hModule = LoadLibrary("User32.DLL");
        if (hModule != NULL)
        {
            typedef BOOL (WINAPI *FUNC)(HWND,COLORREF,BYTE,DWORD);
            //获得 SetLayeredWindowAttributes 函数指针
            FUNC func = (FUNC)GetProcAddress(hModule,"SetLayeredWindowAttributes");
            if (func != NULL)
            {
                func(GetSafeHwnd(),0,128,2);
            }
            FreeLibrary(hModule);
        }
    }

    15 窗口闪烁

    使窗口闪烁可以调用 CWnd::FlashWindow 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    void CDemoDlg::OnButton22()
    {
        //设置定时器
        SetTimer(1,1000,NULL);
    }
     
    void CDemoDlg::OnButton23()
    {
        //关闭定时器
        KillTimer(1);
        //窗口返回原始状态
        FlashWindow(FALSE);
    }
     
    void CDemoDlg::OnTimer(UINT nIDEvent)
    {
        if (nIDEvent == 1)
        {
            //窗口从一种状态闪烁到另一种状态
            FlashWindow(TRUE);
        }  
        CDialog::OnTimer(nIDEvent);
    }

    16 图片窗口

    实现图片窗口,首先调用 CRgn::CreateRectRgn 和 CRgn::CombineRgn 函数创建并合并多个区域,然后调用 CWnd::SetWindowRgn 函数将其设置为窗口区域。

    VC对话框如何添加WM_ERASEBKGND消息(OnEraseBkgnd函数):

    http://guohaiyang.blog.163.com/blog/static/3213403720081027104147/

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    void CDemoDlg::OnButton24()
    {
        CRect rect;
        GetWindowRect(&rect);
        //加载位图
        CBitmap bmp;
        bmp.LoadBitmap(IDB_BITMAP);
        //将位图选入设备环境
        CDC dc;
        CDC *pDC = GetDC();
        dc.CreateCompatibleDC(pDC);
        dc.SelectObject(&bmp);
        //将位图中黑色区域变成透明区域
        CRgn rgn1;
        rgn1.CreateRectRgn(0,0,rect.Width(),rect.Height());
        for (int x = 0;x < rect.Width();x++)
        {
            for (int y = 0;y < rect.Height();y++)
            {
                COLORREF cr = dc.GetPixel(x,y);
                if (cr == RGB(0,0,0))
                {
                    CRgn rgn2;
                    rgn2.CreateRectRgn(x,y,x+1,y+1);
                    rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR);
                }
            }
        }
        //设置窗口区域
        SetWindowRgn((HRGN)rgn1,TRUE);
        ReleaseDC(pDC);
    }
    //添加 WM_ERASEBKGND 消息处理函数
    BOOL CDemoDlg::OnEraseBkgnd(CDC* pDC)
    {
        CRect rect;
        GetWindowRect(&rect);
        CBitmap bmp;
        bmp.LoadBitmap(IDB_BITMAP);
        CDC dc;
        dc.CreateCompatibleDC(pDC);
        dc.SelectObject(&bmp);
        pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);
        return TRUE;
    }

    17 动画窗口

    实现动画窗口,可以调用 SDK 的 AnimateWindow 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    BOOL CDemoDlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
        // ...
            //窗口居中
        CenterWindow();
        //显示动画窗口
        AnimateWindow(GetSafeHwnd(), 3000, AW_BLEND);
        return TRUE;
    }

    18 桌面窗口

    获得桌面窗口,可以调用 CWnd::GetDesktopWindow 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void CDemoDlg::OnButton25()
    {
        //获得桌面窗口
        CWnd* pWnd = CWnd::GetDesktopWindow();
        //获得窗口大小
        CRect rect;
        pWnd->GetClientRect(rect);
        CString strText = _T("");
        strText.Format(_T("桌面窗口大小:%dX%d"),rect.Width(),rect.Height());
        AfxMessageBox(strText);
    }

    19 最小化桌面所有窗口

    Window 中可以利用快捷键 Win+M 最小化所有窗口。因此,可以通过向任务栏窗口发送 ID 为 0x1F5(Win+M) 的 WM_HOTKEY 消息,使桌面所有窗口最小化。首先调用 CWnd::FindWindow 函数获得窗口,然后调用 CWnd::SendMessage 函数向窗口发送消息。

    1
    2
    3
    4
    5
    6
    7
    void CDemoDlg::OnButton26()
    {
        //获得任务栏窗口
        CWnd* pWnd = CWnd::FindWindow(_T("Shell_TrayWnd"),NULL);
        //发送ID为0x1F5(Win+M)的WM_HOTKEY消息
        pWnd->SendMessage(WM_HOTKEY,0x1F5);
    }

    20 获取任务栏窗口

    获得任务栏窗口,可以调用 CWnd::FindWinow 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void CDemoDlg::OnButton27()
    {
        //获得任务栏窗口
        CWnd* pWnd = CWnd::FindWindow(_T("Shell_TrayWnd"),NULL);
        //获得窗口大小
        CRect rect;
        pWnd->GetClientRect(rect);
        CString strText = _T("");
        strText.Format(_T("任务栏窗口大小:%dX%d"),rect.Width(),rect.Height());
        AfxMessageBox(strText);
    }

    21 显示或隐藏任务栏

    显示或隐藏任务栏,首先调用 CWnd::FindWindow 函数获得窗口,然后调用 CWnd::ShowWindow 函数隐藏或显示窗口。 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    void CDemoDlg::OnButton28()
    {
        //获得任务栏窗口
        CWnd* pWnd = CWnd::FindWindow(_T("Shell_TrayWnd"),NULL);
        //隐藏窗口
        if (pWnd->IsWindowVisible())
        {
            pWnd->ShowWindow(SW_HIDE);
        }
    }
     
    void CDemoDlg::OnButton29()
    {
        //获得任务栏窗口
        CWnd* pWnd = CWnd::FindWindow(_T("Shell_TrayWnd"),NULL);
        //显示窗口
        if (!pWnd->IsWindowVisible())
        {
            pWnd->ShowWindow(SW_SHOW);
        }
         
    }

    22 枚举桌面所有顶层窗口

    BOOL CDemoDlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
        // ...
        //初始化列表框控件
        CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LIST);
        pList->ModifyStyle(LVS_ICON | LVS_SMALLICON | LVS_LIST,LVS_REPORT);
        pList->SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
        pList->InsertColumn(0,_T("窗口类名"),LVCFMT_LEFT,115);
        pList->InsertColumn(1,_T("窗口标题"),LVCFMT_LEFT,150);
        return TRUE;
    }

    枚举桌面所有顶层窗口有以下两种方法:

    a 调用 CWnd::GetDesktopWindow 和 CWnd::GetWindow 函数:首先调用 CWnd::GetDesktopWindow 函数,获得桌面窗口,然后调用 CWnd::GetWindow 函数,枚举所有子窗口。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    void CDemoDlg::OnButton30()
    {
        CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LIST);
        pList->DeleteAllItems();
        pList->SetRedraw(FALSE);
        //获得桌面窗口
        CWnd* pDesktopWnd = CWnd::GetDesktopWindow();
        //获得第一个子窗口
        CWnd* pWnd = pDesktopWnd->GetWindow(GW_CHILD);
        while(pWnd != NULL)
        {
            int nItem = pList->GetItemCount();
            //获得窗口类名
            CString strClassName = _T("");
            ::GetClassName(pWnd->GetSafeHwnd(),strClassName.GetBuffer(256),256);
            strClassName.ReleaseBuffer();
            pList->InsertItem(nItem,strClassName);
            //获得窗口标题
            CString strWindowText = _T("");
            ::GetWindowText(pWnd->GetSafeHwnd(),strWindowText.GetBuffer(256),256);
            strWindowText.ReleaseBuffer();
            pList->SetItemText(nItem,1,strWindowText);
            //继续获得下一个子窗口
            pWnd =  pWnd->GetWindow(GW_HWNDNEXT);
        }
        pList->SetRedraw(TRUE);
    }

    b 调用 SDK 的 EnumWindows 函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    //添加全局函数
    BOOL CALLBACK EnumWndPorc(HWND hWnd,LPARAM lParam)
    {
        if (hWnd == NULL)
        {
            return FALSE;
        }
        CListCtrl* pList = (CListCtrl*)lParam;
        int nItem = pList->GetItemCount();
        //获得窗口类名
        CString strClassName = _T("");
        ::GetClassName(hWnd,strClassName.GetBuffer(256),256);
        strClassName.ReleaseBuffer();
        pList->InsertItem(nItem,strClassName);
        //获得窗口标题
        CString strWindowText = _T("");
        ::GetWindowText(hWnd,strWindowText.GetBuffer(256),256);
        strWindowText.ReleaseBuffer();
        pList->SetItemText(nItem,1,strWindowText);
        return TRUE;
    }
     
    void CDemoDlg::OnButton31()
    {
        CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LIST);
        pList->DeleteAllItems();
        pList->SetRedraw(FALSE);
        //枚举窗口
        ::EnumWindows(EnumWndPorc,(LPARAM)pList);
        pList->SetRedraw(TRUE);
    }

      

    作者:爱玩C
    邮箱:iwanc@qq.com
    出处:http://www.iwanc.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    转自:http://www.cnblogs.com/iwanc/archive/2013/06/09/2985807.html

  • 相关阅读:
    LeetCode 1245. Tree Diameter
    LeetCode 1152. Analyze User Website Visit Pattern
    LeetCode 1223. Dice Roll Simulation
    LeetCode 912. Sort an Array
    LeetCode 993. Cousins in Binary Tree
    LeetCode 1047. Remove All Adjacent Duplicates In String
    LeetCode 390. Elimination Game
    LeetCode 1209. Remove All Adjacent Duplicates in String II
    LeetCode 797. All Paths From Source to Target
    LeetCode 1029. Two City Scheduling
  • 原文地址:https://www.cnblogs.com/vranger/p/3986653.html
Copyright © 2011-2022 走看看