Windows 中透明窗体与系统托盘实现详解

来源:互联网 发布:php安装图文教程 编辑:程序博客网 时间:2024/05/07 23:42

 自从windows2000起新的windows系统都支持,透明窗体这一特性,这个特性在windows系统上用VC编程实现起来

非常简单下面我就具体来介绍一下具体的实现步骤.

以MFC对话框程序为例其它依原理类推.

在对话框的OnInitDialog()函数中加入如下代码

    SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,
        GetWindowLong(
this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000); 
    HINSTANCE hInst 
= LoadLibrary("User32.DLL"); 
    
    
if(hInst) 
    { 
        typedef BOOL (WINAPI 
*MYFUNC)(HWND,COLORREF,BYTE,DWORD); 
        MYFUNC fun 
= NULL; 
        
//取得SetLayeredWindowAttributes函数指针 
        fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes"); 
        
if(fun)fun(this->GetSafeHwnd(),0,128,2); 
        FreeLibrary(hInst); 
    }

下面我来解释一下这段代码的作用,首先设置窗口风格用SetWindowLong,这里要注意"^0x80000"这个是在原有

窗口风格的基础上加入新的特性,我的xp sp2 sdk中没有对这个数定义.但可以肯定这是新加入的窗口特性

也就是透明窗口的特性.但只设置了这个位,还不够,我们还需要使用SetLayeredWindowAttributes函数来设定

窗口的透明度.首先加载定义这个函数的动态连接库User32.dll.

这里我感到很奇怪,在我的SDK当中已有SetLayeredWindowAttributes函数的声明,可当我编译是连接了USER32.lib

可我直接使用SetLayeredWindowAttributes函数时还会出现"nresolved external symbol __imp__SetLayeredWindowAttributes@16" 难道是USER32的导出库中根本没有声明SetLayeredWindowAttributes,这个我不得而知,还好我们可以将他当作未声明的函数来调用,就像如上的代码一样.

好了这个就不赘述了,就是一个标准的调用未声明函数的方法.

下面我来讲讲系统托盘程序的实现方法

一样非常简单首先声明一个NOTIFYICONDATA结构体类型成员变量m_ntfd.这个结构体是系统储存托盘图标

数据的,我们要实现的是当程序最小化时将图标最小化到托盘.当双击托盘图标时,还原原窗口.

首先我们来响应窗口最小化消息,并在其中隐藏主窗口,并创建托盘图标.在OnSysCommand函数中加入如下

代码:

 

if(SC_MINIMIZE==nID)
    {
        
        memset(
&m_ntfd,0,sizeof(m_ntfd));
        m_ntfd.cbSize
=(DWORD)sizeof(NOTIFYICONDATA);
        m_ntfd.hWnd
=m_hWnd;  
        m_ntfd.uID
=IDR_MAINFRAME;
        m_ntfd.uFlags
=NIF_ICON|NIF_MESSAGE|NIF_TIP;
        m_ntfd.hIcon
=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
        m_ntfd.uCallbackMessage
=UM_CALLBACK;
        strcpy(m_ntfd.szTip,
"hello");
        
        Shell_NotifyIcon(NIM_ADD,
&m_ntfd);
        ShowWindow(SW_HIDE);
        
    }

其中NIF_ICON|NIF_MESSAGE|NIF_TIP三个标志位说明托盘图标生效,并能向主窗口(m_ntfd.hWnd=m_hWnd中定义的)发送消息.并且还会有个TIP这里我们让它显示的是"hello"

m_ntfd.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));这里加载

一个托盘图标,我们用的主框架的图标.

m_ntfd.uCallbackMessage=UM_CALLBACK;这里是当托盘响应鼠标或键盘事件时发送的消息.我们将在主窗口

中响应这个消息.首先我们定义它

#define UM_CALLBACK  WM_USER+10

然后写声明消息响应函数写 MESSAGE  MAP 最后定义消息响应函数:

afx_msg void CDEMODlg::oncallback(WPARAM wParam,LPARAM lParam)
{
if(WM_LBUTTONDBLCLK==lParam)
    {
        PostMessage(WM_SYSCOMMAND,SC_RESTORE,
0);
        Shell_NotifyIcon(NIM_DELETE,
&m_ntfd);
        ShowWindow(SW_SHOW);

    }
}

这样我们所需要的功能就实现了.

两个有意思又简单的功能就说道这里了.