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

 自从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);

    }
}

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

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

你可能感兴趣的:(windows,shell,user,callback,fun,winapi)