使用dwm桌面窗口管理器实现Win7桌面绘图

DWM 是一种新界面,用于管理如何将运行和呈现的各种窗口合并到 Windows Vista 桌面上。Windows® Presentation Foundation (WPF) 提供了一种更高级别的层,控制着到桌面层的呈现,Windows Display Driver Model (WDDM) 用于处理到显示器的实际低级呈现。本文仅讨论如何使用 DWM 界面。有关该主题的详细信息,请阅读 David Chappell 编写的 MSDN 文章“Windows Presentation Foundation 简介”( msdn2.microsoft.com/aa663364.aspx )。WDDM 之所以是本文通篇关注的唯一内容,是因为它可以通过 DWM 界面实现新效果,而且可以修复一些特定问题。
DWM 的技术概览
在除 Windows Vista Home Basic 之外的所有 Windows Vista 版本中均提供 DWM 界面,通过 dwm.exe 可以启动该界面。系统中的所有应用程序都可以从 DWM 获益,而无需进行修改或重新编译。不过,选择利用特定 DWM 功能的应用程序可以调用 dwmapi.dll 中的界面(DWM 的公用界面),然后将这些界面传递到 dwm.exe。界面声明可在 dwmapi.h 中找到,并且可以从 windowssdk.msdn.microsoft.com 在线获取最新的 API 信息。
Windows Vista 在设计上对每个窗口都使用图形加速器,而不是仅针对三维 DirectX® 应用程序。为了实现这一点,DWM 需要与 WDDM 通信,后者是图形处理器和视频内存的最终所有者。(DWM 依赖于 milcore.dll,后者是与 Windows Presentation Foundation 共享的组件,用于输出和呈现到 DirectX。)呈现操作由 DWM 中的单独线程处理,拥有 DirectX 设备的用户无法对其进行访问。另外,大多数应用程序本身有处理呈现操作和 UI 的线程(如典型的 Win32® 应用程序中的 USER 消息弹出线程),但其与 DWM 的呈现线程不冲突。DWM 获取一个窗口列表,并在树结构中管理其位图,然后将其组合到最终桌面。换言之,每个应用程序均呈现自己的位图,然后由 DWM 进行组合。
应用程序的主窗口线程呈现其场景,DWM 呈现线程对该场景进行访问,并且呈现线程通过其 DirectX 界面更新桌面。传递的信息被压缩为仅对以前呈现的更改(差异),大型数据(如图像)则置于共享内存中。这就潜在地允许在一台计算机上生成场景,而最终的呈现操作可以在另一台计算机上完成。使用过 OpenGL 的三维程序员会对此体系结构非常熟悉,它允许服务器管理三维场景,并且仅将差异发送到客户端计算机。您可以分布式呈现三维场景,并让其在任何数量的客户端计算机上使用完全硬件加速运行。此体系结构使 DWM 能够为远程桌面方案提供一级支持。
尽管 Windows Vista 将与旧版 Windows XP 兼容驱动程序一起运行,但需要让 WDDM 视频驱动程序来获得所有 DWM 功能。与某些假定情况相反,DWM 不需要 DirectX 10,但它确实需要更多的视频/纹理内存和支持 Shader Model 2.0 或更高版本的视频卡。使用 WDDM 的最大改变是它引入了 Video Memory Manager (VidMM),后者可以在系统内存和视频内存之间交换视频内存分布。这意味着 WDDM 可以虚拟化视频卡的资源,因而在共享和交换视频内存方面以及在不同应用程序的不同线程之间对图形处理器进行上下文切换方面可以做得更好。以前几乎不可能稳定地运行多个三维应用程序,原因是驱动程序无法处理上下文切换。而且在 WDDM 出现之前,没有可用的正式计划,因此通常会出现一个 DirectX 应用程序耗尽其他应用程序的资源。而使用 WDDM 就很难发生这种情况。Windows Vista 对驱动程序的控制也严格得多,并要求比以前 Windows 版本的驱动程序更强大可靠。
另外请注意,DirectX 10 是一个仅用于 Windows Vista 的 API。为 DirectX 以前版本设计的应用程序将运行于旧版 DirectX API 实现(预计将被称为 DirectX 9 L)上。这将是 WDDM 之前的驱动程序支持的最后版本。DirectX 9 L 应用程序预计将运行于装有 DirectX 9 L 的 Windows XP 上和 Windows Vista 上。DirectX 10 不包含旧式界面。
一些常见的组合函数
如果您希望在程序中使用桌面组合功能,则需要查询和设置各种 DWM 参数。例如,如果某些应用程序切换为全屏显示,然后 DWM 关闭组合,并以不透明的桌面背景颜色呈现,那么您的应用程序应识别这种情况并禁用特定于组合的功能。下面是将您的程序与 DWM 集成的一些基本函数:
DwmEnableComposition 启用或禁用 DWM 组合。DWM 将在当前进程中或直到重设前保持此设置。更改设置会导致发出 WM_DWMCOMPOSITIONCHANGED 通知。多数应用程序不需要调用此函数,但您可能需要监视 Windows 的最终消息。
DwmIsCompositionEnabled 获取桌面启用 DWM 组合的状态。
DwmSetWindowAttribute 为窗口设置指定的 DWM 属性的值,控制如何处理 DWM 过渡,是否允许非客户端呈现,以及 Flip 3D 将如何处理窗口。例如,如果对某个窗口关闭非客户端呈现,则稍后扩展框架或使窗口后面的内容变模糊的要求将会失败。
DwmGetWindowAttribute 为指定窗口检索指定 DWMWINDOWATTRIBUTE 的当前值。
DwmGetColorizationColor 检索用于 DWM 玻璃组合的当前颜色。此值基于当前颜色方案。更改此设置将导致发出 WM_WMCOLORIZATIONCOLORCHANGED 通知。
DwmDefWindowProc 在使用 WM_NCHITTEST 通知进行调用时以及由于在扩展了客户端框架而需要处理 WM_NCCALCSIZE 及类似消息时,使 DWM 命中测试位于非客户端区域。
在您的程序中呈现玻璃效果相当简单。DWM 为此提供了两个函数:
DwmExtendFrameIntoClientArea 一个简单的函数,将非客户端框架的边缘扩展到窗口内。
DwmEnableBlurBehindWindow 一种更为复杂的函数,对玻璃效果的呈现方式提供更多的控制。
由于所有组合窗口都通过 DWM 呈现到一个屏外窗口,然后进行组合后再呈现到桌面上,因此获取这些图像并提供应用程序的实时缩略图表示并不困难。DWM 为您提供了四个函数来控制缩略图的呈现方式:
DwmQueryThumbnailSourceSize 返回 DWM 缩略图的原始大小。
DwmRegisterThumbnail 创建目标窗口和源窗口之间的缩略图关系。
DwmUnregisterThumbnail 删除由 DwmRegisterThumbnail 创建的 DWM 缩略图关系。
DwmUpdateThumbnailProperties 更新给定缩略图的属性。
DWM 提供了五个函数用于微调 DWM 的呈现方式,但这些函数超出了本文的讨论范围。

以上来自http://blog.csdn.net/donetk/archive/2008/05/02/2364247.aspx


现在开始实现桌面绘图:

首先用创建一个基于对话框的MFC工程Demo
然后再OnInitDialog添加如下代码

BOOL CDemo2Dlg::OnInitDialog()
{

   系统自己生成的代码
   // TODO: 在此添加额外的初始化代
  SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetExStyle() | WS_EX_LAYERED);
  VERIFY(::SetLayeredWindowAttributes(m_hWnd,
                                            m_transparencyKey,   //要透明或要玻璃化的掩码色 COLORREF 类型 可任意设置
                                            0,
                                            LWA_COLORKEY));

  bmp.CreateCompatibleBitmap(this->GetDC(),1000,1000);          //bmp是CBitmap对象
  memDC.CreateCompatibleDC(NULL);                                     //memDC是CDC对象
  memDC.SelectObject(&bmp);
  memDC.FillSolidRect(0,0,1000,1000,RGB(255,255,255));
  return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
然后再OnEraseBack添加如下代码将客户区的背景填充为掩码色,以达到透明效果

 

 

 

BOOL CDemo2Dlg::OnEraseBkgnd(CDC* pDC)
{
   //TODO: 在此添加消息处理程序代码和/或调用默认值
    CRect rect;
    GetClientRect(&rect);
    pDC->FillSolidRect(&rect, m_transparencyKey);
    return true;

}
然后要透明化就执行如下代码

        const MARGINS margins = {0};
        DwmExtendFrameIntoClientArea(m_hWnd,&margins);

要玻璃化就执行如下代码

        const MARGINS margins = { -1 };
        DwmExtendFrameIntoClientArea(m_hWnd,&margins);

可将以上代码分别写在不同按钮的响应事件中

这样就可以利用GDI在透明的对话框上绘图了,并且绘制出的图形不会是半透明的

绘图操作如下

void CDemo2Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 pt_start=point;
 
 CDialogEx::OnLButtonDown(nFlags, point);
}


void CDemo2Dlg::OnLButtonUp(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 CPen brushPen(PS_SOLID, 5, RGB(255, 0, 0));
  memDC.SelectObject(&brushPen);
 memDC.MoveTo(pt_start);
 memDC.LineTo(point);
 this->Invalidate();
 CDialogEx::OnLButtonUp(nFlags, point);
}
OnPaint方法中添加如下代码

this->GetDC()->TransparentBlt(0,0,1000,1000,&memDC,0,0,1000,1000,RGB(255,255,255));//最后一个参数是bmp的背景颜色,这里是要把bmp的背景色被透明掉。

假如在OnInitDialog中缺少

SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetExStyle() | WS_EX_LAYERED);
  VERIFY(::SetLayeredWindowAttributes(m_hWnd,
                                            m_transparencyKey,   //要透明或要玻璃化的掩码色 COLORREF 类型 可任意设置
                                            0,
                                            LWA_COLORKEY));
并且没有OnEraseBkGnd方法,那么要让对话框透明就让OnCltColor返回一个空画刷代码如下

HBRUSH CDemo2Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH hbr = (HBRUSH)::CreateSolidBrush(NULL_BRUSH);
 return NULL;
}
这样对话框也能达到以上效果,不过用GDI绘图时所绘制的图形就变成半透明的了,这时就应该用GDI+绘图了,GDI+绘图如下

 Bitmap bit(1000,1000);
 Graphics* g=Graphics::FromImage(&bit);
 Pen pen(Color(255,0,255,0),2);
 clock_t start=clock();
 for(int i=1;i<=100;i++)
 {
  g->DrawLine(&pen,0,i*8,999,i*8);
 }
 Graphics gc(this->GetDC()->m_hDC);
 gc.DrawImage(&bit,0,0);

 全部代码如下:


// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件

#pragma once

#ifndef _SECURE_ATL
#define _SECURE_ATL 1
#endif

#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
#endif

#include "targetver.h"

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的

// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
#define _AFX_ALL_WARNINGS

#include          // MFC 核心组件和标准组件
#include          // MFC 扩展


#include         // MFC 自动化类
#include
#pragma comment(lib,"dwmapi")
#include
using namespace Gdiplus;

#ifndef _AFX_NO_OLE_SUPPORT
#include            // MFC 对 Internet Explorer 4 公共控件的支持
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include              // MFC 对 Windows 公共控件的支持
#endif // _AFX_NO_AFXCMN_SUPPORT

#include      // 功能区和控件条的 MFC 支持

#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:/"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'/"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:/"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'/"")
#else
#pragma comment(linker,"/manifestdependency:/"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'/"")
#endif
#endif



// Demo2.h : PROJECT_NAME 应用程序的主头文件
//

#pragma once

#ifndef __AFXWIN_H__
 #error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif

#include "resource.h"  // 主符号


// CDemo2App:
// 有关此类的实现,请参阅 Demo2.cpp
//

class CDemo2App : public CWinApp
{
public:
 CDemo2App();

// 重写
public:
 virtual BOOL InitInstance();

// 实现

 DECLARE_MESSAGE_MAP()
};

extern CDemo2App theApp;
// Demo2.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "Demo2.h"
#include "Demo2Dlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CDemo2App

BEGIN_MESSAGE_MAP(CDemo2App, CWinApp)
 ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CDemo2App 构造

CDemo2App::CDemo2App()
{
 // 支持重新启动管理器
 m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;

 // TODO: 在此处添加构造代码,
 // 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CDemo2App 对象

CDemo2App theApp;


// CDemo2App 初始化
ULONG_PTR gdiplusToken;
BOOL CDemo2App::InitInstance()
{
 GdiplusStartupInput gdiplusStartupInput;
 GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
 // 如果一个运行在 Windows XP 上的应用程序清单指定要
 // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
 //则需要 InitCommonControlsEx()。否则,将无法创建窗口。
 INITCOMMONCONTROLSEX InitCtrls;
 InitCtrls.dwSize = sizeof(InitCtrls);
 // 将它设置为包括所有要在应用程序中使用的
 // 公共控件类。
 InitCtrls.dwICC = ICC_WIN95_CLASSES;
 InitCommonControlsEx(&InitCtrls);

 CWinApp::InitInstance();


 AfxEnableControlContainer();

 // 创建 shell 管理器,以防对话框包含
 // 任何 shell 树视图控件或 shell 列表视图控件。
 CShellManager *pShellManager = new CShellManager;

 // 标准初始化
 // 如果未使用这些功能并希望减小
 // 最终可执行文件的大小,则应移除下列
 // 不需要的特定初始化例程
 // 更改用于存储设置的注册表项
 // TODO: 应适当修改该字符串,
 // 例如修改为公司或组织名
 SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

 CDemo2Dlg dlg;
 m_pMainWnd = &dlg;
 INT_PTR nResponse = dlg.DoModal();
 if (nResponse == IDOK)
 {
  // TODO: 在此放置处理何时用
  //  “确定”来关闭对话框的代码
 }
 else if (nResponse == IDCANCEL)
 {
  // TODO: 在此放置处理何时用
  //  “取消”来关闭对话框的代码
 }

 // 删除上面创建的 shell 管理器。
 if (pShellManager != NULL)
 {
  delete pShellManager;
 }

 // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
 //  而不是启动应用程序的消息泵。
 return FALSE;
}


// Demo2Dlg.h : 头文件
//

#pragma once
#include "afxwin.h"


// CDemo2Dlg 对话框
class CDemo2Dlg : public CDialogEx
{
// 构造
public:
 CDemo2Dlg(CWnd* pParent = NULL); // 标准构造函数

// 对话框数据
 enum { IDD = IDD_DEMO2_DIALOG };

 protected:
 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持


// 实现
protected:
 HICON m_hIcon;

 // 生成的消息映射函数
 virtual BOOL OnInitDialog();
 afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
 afx_msg void OnPaint();
 afx_msg HCURSOR OnQueryDragIcon();
 DECLARE_MESSAGE_MAP()
public:
 afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
 afx_msg void OnBnClickedButton1();
 afx_msg void OnBnClickedButton2();
 CButton button;
 const COLORREF m_transparencyKey;
 afx_msg BOOL OnEraseBkgnd(CDC* pDC);
 bool isTransparentOrNot;
 afx_msg void OnBnClickedButton3();
 CDC memDC;
 CBitmap bmp;
 CPoint pt_start;
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
 afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
};


// Demo2Dlg.cpp : 实现文件
//

#include "stdafx.h"
#include "Demo2.h"
#include "Demo2Dlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace Gdiplus;

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
 CAboutDlg();

// 对话框数据
 enum { IDD = IDD_ABOUTBOX };

 protected:
 virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
 DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CDemo2Dlg 对话框


CDemo2Dlg::CDemo2Dlg(CWnd* pParent /*=NULL*/)
 : CDialogEx(CDemo2Dlg::IDD, pParent), m_transparencyKey(0xc8c9ca)
 , isTransparentOrNot(true)
{
 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDemo2Dlg::DoDataExchange(CDataExchange* pDX)
{
 CDialogEx::DoDataExchange(pDX);
 DDX_Control(pDX, IDC_BUTTON2, button);
}

BEGIN_MESSAGE_MAP(CDemo2Dlg, CDialogEx)
 ON_WM_SYSCOMMAND()
 ON_WM_PAINT()
 ON_WM_QUERYDRAGICON()
 ON_WM_CTLCOLOR()
 ON_BN_CLICKED(IDC_BUTTON1, &CDemo2Dlg::OnBnClickedButton1)
 ON_BN_CLICKED(IDC_BUTTON2, &CDemo2Dlg::OnBnClickedButton2)
 ON_WM_ERASEBKGND()
 ON_BN_CLICKED(IDC_BUTTON3, &CDemo2Dlg::OnBnClickedButton3)
 ON_WM_LBUTTONDOWN()
 ON_WM_LBUTTONUP()
END_MESSAGE_MAP()


// CDemo2Dlg 消息处理程序

BOOL CDemo2Dlg::OnInitDialog()
{
 CDialogEx::OnInitDialog();

 // 将“关于...”菜单项添加到系统菜单中。

 // IDM_ABOUTBOX 必须在系统命令范围内。
 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 ASSERT(IDM_ABOUTBOX < 0xF000);

 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
  BOOL bNameValid;
  CString strAboutMenu;
  bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
  ASSERT(bNameValid);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
 }

 // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
 //  执行此操作
 SetIcon(m_hIcon, TRUE);   // 设置大图标
 SetIcon(m_hIcon, FALSE);  // 设置小图标

 // TODO: 在此添加额外的初始化代
 
  SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetExStyle() | WS_EX_LAYERED);
        VERIFY(::SetLayeredWindowAttributes(m_hWnd,
                                            m_transparencyKey,
                                            0,
                                            LWA_COLORKEY));
  bmp.CreateCompatibleBitmap(this->GetDC(),1000,1000);
  memDC.CreateCompatibleDC(NULL);
  memDC.SelectObject(&bmp);
  memDC.FillSolidRect(0,0,1000,1000,RGB(255,255,255));
  
 return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CDemo2Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
 

 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
 {
  CAboutDlg dlgAbout;
  dlgAbout.DoModal();
 }
 else
 {
  CDialogEx::OnSysCommand(nID, lParam);
 }
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CDemo2Dlg::OnPaint()
{
 if (IsIconic())
 {
  CPaintDC dc(this); // 用于绘制的设备上下文

  SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);

  // 使图标在工作区矩形中居中
  int cxIcon = GetSystemMetrics(SM_CXICON);
  int cyIcon = GetSystemMetrics(SM_CYICON);
  CRect rect;
  GetClientRect(&rect);
  int x = (rect.Width() - cxIcon + 1) / 2;
  int y = (rect.Height() - cyIcon + 1) / 2;

  // 绘制图标
  dc.DrawIcon(x, y, m_hIcon);
  
 }
 else
 {
  CDialogEx::OnPaint();
  
  this->GetDC()->TransparentBlt(0,0,1000,1000,&memDC,0,0,1000,1000,RGB(255,255,255));
 } 
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CDemo2Dlg::OnQueryDragIcon()
{
 return static_cast(m_hIcon);
}

HBRUSH CDemo2Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH hbr = (HBRUSH)::CreateSolidBrush(NULL_BRUSH);
 return NULL;
}


void CDemo2Dlg::OnBnClickedButton1()
{
 Bitmap bit(1000,1000);
 Graphics* g=Graphics::FromImage(&bit);
 Pen pen(Color(255,0,255,0),2);
 clock_t start=clock();
 for(int i=1;i<=100;i++)
 {
  g->DrawLine(&pen,0,i*8,999,i*8);
 }
 Graphics gc(this->GetDC()->m_hDC);
 gc.DrawImage(&bit,0,0);
 clock_t time=clock()-start;
 float ftime=time/1000.0f;
 CString str;
 str.Format(_T("%.1f frame per second of GDIPLUS/n"),100/ftime);
 AfxMessageBox(str);
}


void CDemo2Dlg::OnBnClickedButton2()
{
 /* HRGN hRgn = ::CreateRectRgn(0,0,1,1);
  DWM_BLURBEHIND bb = {0};
  bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
  bb.fEnable = true;
  bb.hRgnBlur = hRgn;
  DwmEnableBlurBehindWindow(this->m_hWnd, &bb);  */
 if(isTransparentOrNot)
 {
        const MARGINS margins = {0};
        DwmExtendFrameIntoClientArea(m_hWnd,&margins);
  LPCTSTR   text=_T("玻璃");
  button.SetWindowText( text);
  isTransparentOrNot=false;
 }
 else
 {
  const MARGINS margins = { -1 };
        DwmExtendFrameIntoClientArea(m_hWnd,&margins);
  LPCTSTR   text=_T("透明");
  button.SetWindowText( text);
  isTransparentOrNot=true;
 }
}


BOOL CDemo2Dlg::OnEraseBkgnd(CDC* pDC)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 CRect rect;
    GetClientRect(&rect);
    pDC->FillSolidRect(&rect, m_transparencyKey);
    return true;
 COLORREF col(RGB(0,0,0));
 return CDialogEx::OnEraseBkgnd(pDC);
}


void CDemo2Dlg::OnBnClickedButton3()
{
 // TODO: 在此添加控件通知处理程序代码
 CDC memDC;
 CBitmap bmp;
 bmp.CreateCompatibleBitmap(this->GetDC(),1000,1000);
 memDC.CreateCompatibleDC(NULL);
 memDC.SelectObject(&bmp);
 memDC.FillSolidRect(0,0,1000,1000,RGB(255,255,255));
 CPen brushPen(PS_SOLID, 2, RGB(0, 255, 0));
 memDC.SelectObject(&brushPen);
 clock_t start=clock();
 for(int i=1;i<=100;i++)
 {
  memDC.MoveTo(0,i*8);
  memDC.LineTo(999,i*8);
 }
 //this->GetDC()->BitBlt(0,0,1000,1000,&memDC,0,0,SRCCOPY);
 this->GetDC()->TransparentBlt(0,0,1000,1000,&memDC,0,0,1000,1000,RGB(255,255,255));
 clock_t time=clock()-start;
 float ftime=time/1000.0f;
 CString str;
 str.Format(_T("%.1f frame per second of GDI/n"),100/ftime);
 AfxMessageBox(str);
}


void CDemo2Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 pt_start=point;
 
 CDialogEx::OnLButtonDown(nFlags, point);
}


void CDemo2Dlg::OnLButtonUp(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 CPen brushPen(PS_SOLID, 5, RGB(255, 0, 0));
  memDC.SelectObject(&brushPen);
 memDC.MoveTo(pt_start);
 memDC.LineTo(point);
 this->Invalidate();
 CDialogEx::OnLButtonUp(nFlags, point);
}

你可能感兴趣的:(使用dwm桌面窗口管理器实现Win7桌面绘图)