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

  • 相关阅读:
    ACwing(基础)--- 01背包和完全背包、多重背包问题
    Python --- 实战一
    Python --- 正则表达式
    Python --- 网络爬虫
    Python --- 异常处理
    Python --- 文件操作
    Python --- 模块
    Python --- 基础语法
    securecrt颜色设置
    Tomcat启动排查
  • 原文地址:https://www.cnblogs.com/vranger/p/3986653.html
Copyright © 2011-2022 走看看