📄 trayicon_win.cpp
字号:
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* copyright : (C) 2003 by Zhang Yong *
* email : z-yong163@163.com *
***************************************************************************/
#include "trayicon.h"
#include <qwidget.h>
#include <qapplication.h>
#include <qimage.h>
#include <qpixmap.h>
#include <qbitmap.h>
#include <qcursor.h>
#include <qt_windows.h>
static uint MYWM_TASKBARCREATED = 0;
#define MYWM_NOTIFYICON (WM_APP+101)
class TrayIcon::TrayIconPrivate : public QWidget
{
public:
TrayIconPrivate( TrayIcon *object )
: QWidget( 0 ), hIcon( 0 ), iconObject( object )
{
if ( !MYWM_TASKBARCREATED ) {
#if defined(UNICODE)
if ( qWinVersion() & Qt::WV_NT_based )
MYWM_TASKBARCREATED = RegisterWindowMessageW( (TCHAR*)"TaskbarCreated" );
else
#endif
MYWM_TASKBARCREATED = RegisterWindowMessageA( "TaskbarCreated" );
}
}
~TrayIconPrivate()
{
if ( hIcon )
DestroyIcon( hIcon );
}
// the unavoidable A/W versions. Don't forget to keep them in sync!
bool trayMessageA( DWORD msg )
{
bool res;
NOTIFYICONDATAA tnd;
memset( &tnd, 0, sizeof(NOTIFYICONDATAA) );
tnd.cbSize = sizeof(NOTIFYICONDATAA);
tnd.hWnd = winId();
if ( msg != NIM_DELETE ) {
tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage= MYWM_NOTIFYICON;
tnd.hIcon = hIcon;
if ( !iconObject->toolTip().isNull() ) {
// Tip is limited to 63 + NULL; lstrcpyn appends a NULL terminator.
QString tip = iconObject->toolTip().left( 63 ) + QChar();
lstrcpynA(tnd.szTip, (const char*)tip, QMIN( tip.length()+1, 64 ) );
}
}
res = Shell_NotifyIconA(msg, &tnd);
return res;
}
#if defined(UNICODE)
bool trayMessageW( DWORD msg )
{
bool res;
NOTIFYICONDATAW tnd;
memset( &tnd, 0, sizeof(NOTIFYICONDATAW) );
tnd.cbSize = sizeof(NOTIFYICONDATAW);
tnd.hWnd = winId();
if ( msg != NIM_DELETE ) {
tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage= MYWM_NOTIFYICON;
tnd.hIcon = hIcon;
if ( !iconObject->toolTip().isNull() ) {
// Tip is limited to 63 + NULL; lstrcpyn appends a NULL terminator.
QString tip = iconObject->toolTip().left( 63 ) + QChar();
lstrcpynW(tnd.szTip, (TCHAR*)qt_winTchar( tip, FALSE ), QMIN( tip.length()+1, 64 ) );
}
}
res = Shell_NotifyIconW(msg, &tnd);
return res;
}
#endif
bool iconDrawItem(LPDRAWITEMSTRUCT lpdi)
{
if (!hIcon)
return FALSE;
DrawIconEx(lpdi->hDC, lpdi->rcItem.left, lpdi->rcItem.top, hIcon,
0, 0, 0, NULL, DI_NORMAL );
return TRUE;
}
bool winEvent( MSG *m )
{
switch(m->message) {
case WM_DRAWITEM:
return iconDrawItem( (LPDRAWITEMSTRUCT)m->lParam );
case MYWM_NOTIFYICON:
{
QMouseEvent *e = 0;
QPoint gpos = QCursor::pos();
switch (m->lParam)
{
case WM_MOUSEMOVE:
e = new QMouseEvent( QEvent::MouseMove, mapFromGlobal( gpos ), gpos, 0, 0 );
break;
case WM_LBUTTONDOWN:
e = new QMouseEvent( QEvent::MouseButtonPress, mapFromGlobal( gpos ), gpos, LeftButton, LeftButton );
break;
case WM_LBUTTONUP:
e = new QMouseEvent( QEvent::MouseButtonRelease, mapFromGlobal( gpos ), gpos, LeftButton, LeftButton );
break;
case WM_LBUTTONDBLCLK:
e = new QMouseEvent( QEvent::MouseButtonDblClick, mapFromGlobal( gpos ), gpos, LeftButton, LeftButton );
break;
case WM_RBUTTONDOWN:
e = new QMouseEvent( QEvent::MouseButtonPress, mapFromGlobal( gpos ), gpos, RightButton, RightButton );
break;
case WM_RBUTTONUP:
e = new QMouseEvent( QEvent::MouseButtonRelease, mapFromGlobal( gpos ), gpos, RightButton, RightButton );
break;
case WM_RBUTTONDBLCLK:
e = new QMouseEvent( QEvent::MouseButtonDblClick, mapFromGlobal( gpos ), gpos, RightButton, RightButton );
break;
case WM_MBUTTONDOWN:
e = new QMouseEvent( QEvent::MouseButtonPress, mapFromGlobal( gpos ), gpos, MidButton, MidButton );
break;
case WM_MBUTTONUP:
e = new QMouseEvent( QEvent::MouseButtonRelease, mapFromGlobal( gpos ), gpos, MidButton, MidButton );
break;
case WM_MBUTTONDBLCLK:
e = new QMouseEvent( QEvent::MouseButtonDblClick, mapFromGlobal( gpos ), gpos, MidButton, MidButton );
break;
case WM_CONTEXTMENU:
e = new QMouseEvent( QEvent::MouseButtonRelease, mapFromGlobal( gpos ), gpos, RightButton, RightButton );
break;
default:
break;
}
if ( e ) {
bool res = QApplication::sendEvent( iconObject, e );
delete e;
return res;
}
}
break;
default:
if ( m->message == MYWM_TASKBARCREATED ) {
#if defined(UNICODE)
if ( qWinVersion() & Qt::WV_NT_based )
trayMessageW( NIM_ADD );
else
#endif
trayMessageA( NIM_ADD );
}
break;
}
return QWidget::winEvent( m );
}
HICON hIcon;
TrayIcon *iconObject;
};
static HBITMAP createIconMask( const QPixmap &qp )
{
QImage bm = qp.convertToImage();
int w = bm.width();
int h = bm.height();
int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment
uchar *bits = new uchar[bpl*h];
bm.invertPixels();
for ( int y=0; y<h; y++ )
memcpy( bits+y*bpl, bm.scanLine(y), bpl );
HBITMAP hbm = CreateBitmap( w, h, 1, 1, bits );
delete [] bits;
return hbm;
}
static HICON createIcon( const QPixmap &pm )
{
QPixmap maskpm( pm.size(), pm.depth(), QPixmap::NormalOptim );
QBitmap mask( pm.size(), FALSE, QPixmap::NormalOptim );
if ( pm.mask() ) {
maskpm.fill( Qt::black ); // make masked area black
bitBlt( &mask, 0, 0, pm.mask() );
} else {
maskpm.fill( Qt::color1 );
}
bitBlt( &maskpm, 0, 0, &pm);
ICONINFO iconInfo;
iconInfo.fIcon = TRUE;
iconInfo.hbmMask = createIconMask(mask);
iconInfo.hbmColor = pm.hbm();
// yongzh: Also release the bitmap mask before returns!!
HICON icon = CreateIconIndirect( &iconInfo );
DeleteObject(iconInfo.hbmMask);
return icon;
}
void TrayIcon::sysInstall()
{
if ( d )
return;
d = new TrayIconPrivate( this );
d->hIcon = createIcon( pm );
#if defined(UNICODE)
if ( qWinVersion() & Qt::WV_NT_based )
d->trayMessageW( NIM_ADD );
else
#endif
d->trayMessageA( NIM_ADD );
}
void TrayIcon::sysRemove()
{
if ( !d )
return;
#if defined(UNICODE)
if ( qWinVersion() & Qt::WV_NT_based )
d->trayMessageW( NIM_DELETE );
else
#endif
d->trayMessageA( NIM_DELETE );
delete d;
d = 0;
}
void TrayIcon::sysUpdateIcon()
{
if ( !d )
return;
if ( d->hIcon )
DestroyIcon( d->hIcon );
d->hIcon = createIcon( pm );
#if defined(UNICODE)
if ( qWinVersion() & Qt::WV_NT_based )
d->trayMessageW( NIM_MODIFY );
else
#endif
d->trayMessageA( NIM_MODIFY );
}
void TrayIcon::sysUpdateToolTip()
{
if ( !d )
return;
#if defined(UNICODE)
if ( qWinVersion() & Qt::WV_NT_based )
d->trayMessageW( NIM_MODIFY );
else
#endif
d->trayMessageA( NIM_MODIFY );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -