创建透明窗口及其应用--屏幕画笔

本文介绍如何使用SetLayeredWindowAttributes函数使Windows窗口透明,并实现屏幕画笔功能。文章详细展示了设置窗口透明度及颜色透明的具体步骤,并提供了一个完整的屏幕画笔应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

创建透明窗口及其应用--屏幕画笔


 

 

示例代码下载:创建透明窗口(屏幕画笔).zip (请不要直接使用迅雷下载)

注:VC6下编译通过

 

 


 

 

一、使窗口透明其实很简单。就是一个函数SetLayeredWindowAttributes

 

步骤如下:

 

步骤一:让窗口具透明的特性

 

::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);

 

当你不希望窗口透明时,就使这个添加的属性去掉就可以了,如下:

 

 

 //取消透明
  ::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)& ~WS_EX_LAYERED);

 

当然,最后别忘记先定义WS_EX_LAYERED,否则编译时会无法识别WS_EX_LAYERED

#define WS_EX_LAYERED 0x00080000

 

步骤二:获得SetLayeredWindowAttributes函数

 

这个函数需要从USER32.DLL里获得,调用如下。

 

  //获取模块里的函数
HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL")); 

 BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
    (BOOL (WINAPI*)  (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");

 

这样我们就获得了函数SetLayeredWindowAttributes。函数解释如下

 

BOOL SetLayeredWindowAttributes(
HWND hwnd,   handle to the layered window
COLORREF crKey,   specifies the color key
BYTE bAlpha,  value for the blend function
DWORD dwFlags  action);
   其中dwFlags有LWA_ALPHA(值为2)和LWA_COLORKEY(值为1)两种设置,如果LWA_ALPHA被设置的话,
通过bAlpha参数指定窗体的透明度;如果LWA_COLORKEY标志被设置的话,则指定关键色为crKey,
该颜色所覆盖的区域将从窗体去除,去除后的区域将不再进行点击检测,其他颜色则正常显示。
如果阿尔法混合值设置为0,其窗口区域同样不进行点击检测。

 

步骤三:调用函数设置透明。

 

方式一:设置我们指定的颜色透明掉。(第4参数设为1,此时第二个参数是要透明的颜色,其他参数不管)

 

   //设置窗口透明。第4参数为1时,第二个参数是要透明的颜色
   SetLayeredWindowAttributes(m_hWnd,RGB(244,243,238),0,1); 

具体代码如下:(复制粘贴后可以直接使用)

 

 HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL"));
 if (hInst)
 {
  //获取模块里的函数
  BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
    (BOOL (WINAPI*)  (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");

  //函数指针正确获取
  if(SetLayeredWindowAttributes)
  {
   //让窗口具透明的特性
   ::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
   
   //设置窗口透明。第4参数为1时,第二个参数是要透明的颜色
   SetLayeredWindowAttributes(m_hWnd,RGB(244,243,238),0,1); 
  }

  FreeLibrary(hInst); //释放调模块句柄
 }

 

方式二:设置窗口具有某种透明度。(第4参数设为2,此时第三个参数表示透明度的值,其他参数不管)

 

 

   //设置窗口透明。第4参数为2时,第三个参数表示透明度
   SetLayeredWindowAttributes(m_hWnd, 0, 80, 2); 

具体代码如下:(复制粘贴后可以直接使用)

 HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL"));
 if (hInst)
 {
  //获取模块里的函数
  BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
    (BOOL (WINAPI*)  (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");

  //函数指针正确获取
  if(SetLayeredWindowAttributes)
  {
   //让窗口具透明的特性
   ::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
   
   //设置窗口透明。第4参数为2时,第三个参数表示透明度
   SetLayeredWindowAttributes(m_hWnd, 0, 80, 2); 
  }

  FreeLibrary(hInst); //释放调模块句柄
 } 

 


 

二、透明窗口的应用:屏幕画笔

 

1.我们可以创建一个透明的窗口。让其背景色透明掉。比如背景色是RGB(244,243,238),我们使用:

 SetLayeredWindowAttributes(m_hWnd,RGB(244,243,238),0,1);

就可以把背景色去掉。

 

2.当我们使用窗口的屏幕DC画图时,由于颜色不是背景颜色RGB(244,243,238),所以我们画的线都会保留在透明窗口上。

 

3.把窗口的边框去掉,并且覆盖整个屏幕。而且要置窗口为最顶层窗口。这样就可以实现屏幕画笔了。

 

4.画图时,由于窗口透明了,所以我们的鼠标消息不会给透明窗口捕获到。这时我们可以安装一个低级鼠标钩子(之所以要用

低级鼠标钩子因为它够方便,直接写在程序里,不用dll),用于捕获鼠标的说有消息。

 

具体代码如下:当然你也可以参考我上面提供的源代码。

 

 

 

HWND g_hWnd;
POINT LastPoint;
bool IsDrawingLine=false;

BOOL CDemoDlg::OnInitDialog()
{
 CDialog::OnInitDialog();
 SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), TRUE);   // Set big icon
 ::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); //设置窗口最顶
  static CLoadMyLibrary inst(m_hWnd);
 //-----------------------------------------------------------------------------

 g_hWnd=m_hWnd;
 OnButton1();

 return TRUE; 
}


/****************************************************************************
低级鼠标钩子
#define   _WIN32_WINNT   0x0500  //必须在stdafx.h中添加这一句
****************************************************************************/
HHOOK g_LowLevelMouseHook=NULL; //钩子句柄
LRESULT CALLBACK LowLevelMouseProc(int nCode,WPARAM wParam, LPARAM lParam)
{
 if (nCode<0 )
  return CallNextHookEx(g_LowLevelMouseHook,nCode,wParam,lParam);
 
 static POINT point;
 point=(POINT)((MSLLHOOKSTRUCT *)lParam)->pt;

 switch (wParam)
 {
 case WM_LBUTTONDOWN:
  {
   TCHAR ClassName[20]={0};
   ::GetClassName(::WindowFromPoint(point),ClassName,sizeof(ClassName)/sizeof(TCHAR));
   if (_tcscmp(ClassName,_T("Button"))==0)
    break;

   ::ScreenToClient(g_hWnd,&point);
   LastPoint=point;
   IsDrawingLine=true;
   return 1;
  }
  break;
 case WM_LBUTTONUP:
  {
   IsDrawingLine=false;
  }
  break;
 case WM_MOUSEMOVE:
  {
   if (IsDrawingLine)
   {
    ::ScreenToClient(g_hWnd,&point);

    //画鼠标移动痕迹
    HDC hdc=::GetDC(g_hWnd);   //画曲线
    HPEN pen=::CreatePen(PS_SOLID,4,RGB(30,30,30));
    SelectObject (hdc,pen) ;
    ::MoveToEx(hdc,LastPoint.x,LastPoint.y,NULL);
    ::LineTo(hdc,point.x,point.y);
    LastPoint=point;
    DeleteObject(pen);
    ::ReleaseDC(NULL,hdc) ;
   }
   
  }
  break;
 }
 return CallNextHookEx(g_LowLevelMouseHook,nCode,wParam,lParam); //传递钩子信息  
}

 

#define WS_EX_LAYERED 0x00080000

void CDemoDlg::OnButton1()
{
 HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL"));
 if (hInst)
 {
  //获取模块里的函数
  BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
    (BOOL (WINAPI*)  (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");

  //函数指针正确获取
  if(SetLayeredWindowAttributes)
  {
   //让窗口具透明的特性
   ::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
   
   //设置窗口透明。第4参数为1时,第二个参数是要透明的颜色
   SetLayeredWindowAttributes(m_hWnd,RGB(244,243,238),0,1); 
  }

  FreeLibrary(hInst); //释放调模块句柄
 }
}


void CDemoDlg::OnButton5()
{
 HINSTANCE hInst=GetModuleHandle(_T("USER32.DLL"));
 if (hInst)
 {
  //获取模块里的函数
  BOOL (WINAPI *SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD)=
    (BOOL (WINAPI*)  (HWND,COLORREF,BYTE,DWORD))GetProcAddress(hInst,"SetLayeredWindowAttributes");

  //函数指针正确获取
  if(SetLayeredWindowAttributes)
  {
   //让窗口具透明的特性
   ::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)|WS_EX_LAYERED);
   
   //设置窗口透明。第4参数为2时,第三个参数表示透明度
   SetLayeredWindowAttributes(m_hWnd, 0, 80, 2); 
  }

  FreeLibrary(hInst); //释放调模块句柄
 } 
}


void CDemoDlg::OnButton2()
{
 //取消透明
  ::SetWindowLong(m_hWnd,GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE)& ~WS_EX_LAYERED);
}

 

void CDemoDlg::OnButton3()
{
 //取消所有边框
 ::SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE)
  & ~WS_CAPTION & ~WS_THICKFRAME  );  
 ::SetWindowPos(m_hWnd,NULL,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED); 

// //如果有WS_EX_DLGMODALFRAME还要取消WS_EX_DLGMODALFRAME
// ::SetWindowLong(m_hWnd,GWL_EXSTYLE,GetWindowLong(m_hWnd,GWL_EXSTYLE)
//  & ~WS_EX_DLGMODALFRAME);
// ::SetWindowPos(m_hWnd,NULL,0,0,0,0,SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE); 

 int cx=GetSystemMetrics(SM_CXSCREEN);
 int cy=GetSystemMetrics(SM_CYSCREEN);
 ::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,cx,cy,NULL);
}

void CDemoDlg::OnButton4()
{
 //添加标题栏
 ::SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE)
  | WS_CAPTION  );  
 ::SetWindowPos(m_hWnd,HWND_TOPMOST,100,100,400,400,SWP_FRAMECHANGED);
}

 

void CDemoDlg::OnButton6()
{
 if(g_LowLevelMouseHook!=NULL)
  return;

 //start Low Level mouse hook
 g_LowLevelMouseHook=SetWindowsHookEx(WH_MOUSE_LL,LowLevelMouseProc,GetModuleHandle(NULL),0);
 if(!g_LowLevelMouseHook)
  ::MessageBox(m_hWnd,TEXT("SetWindowsHookEx LowLevelMouseProc failed"),NULL,MB_OK);
 
}

void CDemoDlg::OnButton8()
{
 //stop Low Level mouse hook
 UnhookWindowsHookEx(g_LowLevelMouseHook);
 g_LowLevelMouseHook=NULL;
}

 

void CDemoDlg::OnButton7()
{
 ::InvalidateRect(m_hWnd,NULL,true); 
}

 

 

 

希望对你有所帮助!阿弥陀佛!

 


 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值