Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
f689e3fc
Commit
f689e3fc
authored
Feb 19, 2006
by
Robert Shearman
Committed by
Alexandre Julliard
Feb 22, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
shell32: Move systray handling to the explorer process.
parent
0199b441
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
646 additions
and
332 deletions
+646
-332
shell32_main.c
dlls/shell32/shell32_main.c
+0
-1
shell32_main.h
dlls/shell32/shell32_main.h
+0
-3
systray.c
dlls/shell32/systray.c
+126
-325
Makefile.in
programs/explorer/Makefile.in
+3
-2
explorer.c
programs/explorer/explorer.c
+59
-1
systray.c
programs/explorer/systray.c
+435
-0
systray.h
programs/explorer/systray.h
+23
-0
No files found.
dlls/shell32/shell32_main.c
View file @
f689e3fc
...
@@ -1158,7 +1158,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
...
@@ -1158,7 +1158,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
InitCommonControlsEx
(
NULL
);
InitCommonControlsEx
(
NULL
);
SIC_Initialize
();
SIC_Initialize
();
SYSTRAY_Init
();
InitChangeNotifications
();
InitChangeNotifications
();
break
;
break
;
...
...
dlls/shell32/shell32_main.h
View file @
f689e3fc
...
@@ -126,9 +126,6 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI
...
@@ -126,9 +126,6 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI
(((kst)&(MK_CONTROL|MK_SHIFT)) ? DROPEFFECT_COPY :\
(((kst)&(MK_CONTROL|MK_SHIFT)) ? DROPEFFECT_COPY :\
DROPEFFECT_MOVE))
DROPEFFECT_MOVE))
/* Systray */
BOOL
SYSTRAY_Init
(
void
);
HGLOBAL
RenderHDROP
(
LPITEMIDLIST
pidlRoot
,
LPITEMIDLIST
*
apidl
,
UINT
cidl
);
HGLOBAL
RenderHDROP
(
LPITEMIDLIST
pidlRoot
,
LPITEMIDLIST
*
apidl
,
UINT
cidl
);
HGLOBAL
RenderSHELLIDLIST
(
LPITEMIDLIST
pidlRoot
,
LPITEMIDLIST
*
apidl
,
UINT
cidl
);
HGLOBAL
RenderSHELLIDLIST
(
LPITEMIDLIST
pidlRoot
,
LPITEMIDLIST
*
apidl
,
UINT
cidl
);
...
...
dlls/shell32/systray.c
View file @
f689e3fc
/*
/*
*
Systray
*
Systray handling
*
*
* Copyright 1999 Kai Morich <kai.morich@bigfoot.de>
* Copyright 1999 Kai Morich <kai.morich@bigfoot.de>
*
* Copyright 2004 Mike Hearn, for CodeWeavers
* Manage the systray window. That it actually appears in the docking
* Copyright 2005 Robert Shearman
* area of KDE is handled in dlls/x11drv/window.c,
* X11DRV_set_wm_hints using KWM_DOCKWINDOW.
*
*
* This library is free software; you can redistribute it and/or
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* modify it under the terms of the GNU Lesser General Public
...
@@ -22,378 +20,181 @@
...
@@ -22,378 +20,181 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
*/
#include "config.h"
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdarg.h>
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "windef.h"
#include "winbase.h"
#include "winbase.h"
#include "winnls.h"
#include "wingdi.h"
#include "wingdi.h"
#include "winnls.h"
#include "winuser.h"
#include "winuser.h"
#include "shlobj.h"
#include "shellapi.h"
#include "shellapi.h"
#include "shell32_main.h"
#include "commctrl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
shell
);
typedef
struct
SystrayItem
{
HWND
hWnd
;
HWND
hWndToolTip
;
NOTIFYICONDATAW
notifyIcon
;
struct
SystrayItem
*
nextTrayItem
;
}
SystrayItem
;
static
SystrayItem
*
systray
=
NULL
;
static
int
firstSystray
=
TRUE
;
/* defer creation of window class until first systray item is created */
#include "wine/debug.h"
#define ICON_SIZE GetSystemMetrics(SM_CXSMICON)
WINE_DEFAULT_DEBUG_CHANNEL
(
systray
);
/* space around icon (forces icon to center of KDE systray area) */
#define ICON_BORDER 4
static
BOOL
SYSTRAY_ItemIsEqual
(
PNOTIFYICONDATAW
pnid1
,
PNOTIFYICONDATAW
pnid2
)
{
if
(
pnid1
->
hWnd
!=
pnid2
->
hWnd
)
return
FALSE
;
if
(
pnid1
->
uID
!=
pnid2
->
uID
)
return
FALSE
;
return
TRUE
;
}
static
void
SYSTRAY_ItemTerm
(
SystrayItem
*
ptrayItem
)
const
static
WCHAR
classname
[]
=
/* Shell_TrayWnd */
{
'S'
,
'h'
,
'e'
,
'l'
,
'l'
,
'_'
,
'T'
,
'r'
,
'a'
,
'y'
,
'W'
,
'n'
,
'd'
,
'\0'
};
{
if
(
ptrayItem
->
notifyIcon
.
hIcon
)
DestroyIcon
(
ptrayItem
->
notifyIcon
.
hIcon
);
if
(
ptrayItem
->
hWndToolTip
)
DestroyWindow
(
ptrayItem
->
hWndToolTip
);
if
(
ptrayItem
->
hWnd
)
DestroyWindow
(
ptrayItem
->
hWnd
);
return
;
}
/* start timeout of 1 second */
#define SYSTRAY_START_TIMEOUT 1000
static
BOOL
SYSTRAY_Delete
(
PNOTIFYICONDATAW
pn
id
)
static
BOOL
start_systray_process
(
vo
id
)
{
{
SystrayItem
**
ptrayItem
=
&
systray
;
STARTUPINFOW
sinfo
;
PROCESS_INFORMATION
pinfo
;
WCHAR
command_line
[]
=
{
'e'
,
'x'
,
'p'
,
'l'
,
'o'
,
'r'
,
'e'
,
'r'
,
' '
,
'/'
,
's'
,
'y'
,
's'
,
't'
,
'r'
,
'a'
,
'y'
,
0
};
static
const
WCHAR
event_name
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'S'
,
'y'
,
's'
,
't'
,
'r'
,
'a'
,
'y'
,
'I'
,
'n'
,
'i'
,
't'
,
'e'
,
'd'
,
0
};
HANDLE
systray_ready_event
;
DWORD
wait
;
while
(
*
ptrayItem
)
{
TRACE
(
"No tray window found, starting %s
\n
"
,
debugstr_w
(
command_line
));
if
(
SYSTRAY_ItemIsEqual
(
pnid
,
&
(
*
ptrayItem
)
->
notifyIcon
))
{
SystrayItem
*
next
=
(
*
ptrayItem
)
->
nextTrayItem
;
TRACE
(
"%p: %p %s
\n
"
,
*
ptrayItem
,
(
*
ptrayItem
)
->
notifyIcon
.
hWnd
,
debugstr_w
((
*
ptrayItem
)
->
notifyIcon
.
szTip
));
SYSTRAY_ItemTerm
(
*
ptrayItem
);
HeapFree
(
GetProcessHeap
(),
0
,
*
ptrayItem
);
ZeroMemory
(
&
sinfo
,
sizeof
(
sinfo
)
);
*
ptrayItem
=
next
;
sinfo
.
cb
=
sizeof
(
sinfo
)
;
return
TRUE
;
if
(
CreateProcessW
(
NULL
,
command_line
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
sinfo
,
&
pinfo
)
==
0
)
}
{
ptrayItem
=
&
((
*
ptrayItem
)
->
nextTrayItem
);
ERR
(
"Could not start %s, error 0x%lx
\n
"
,
debugstr_w
(
command_line
),
GetLastError
());
return
FALSE
;
}
}
return
FALSE
;
/* not found */
CloseHandle
(
pinfo
.
hThread
);
}
CloseHandle
(
pinfo
.
hProcess
);
static
LRESULT
CALLBACK
SYSTRAY_WndProc
(
HWND
hWnd
,
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
systray_ready_event
=
CreateEventW
(
NULL
,
TRUE
,
FALSE
,
event_name
);
{
if
(
!
systray_ready_event
)
return
FALSE
;
HDC
hdc
;
PAINTSTRUCT
ps
;
switch
(
message
)
{
/* don't guess how long to wait, just wait for process to signal to us
case
WM_PAINT
:
* that it has created the Shell_TrayWnd class before continuing */
{
wait
=
WaitForSingleObject
(
systray_ready_event
,
SYSTRAY_START_TIMEOUT
);
RECT
rc
;
CloseHandle
(
systray_ready_event
);
SystrayItem
*
ptrayItem
=
systray
;
while
(
ptrayItem
)
{
if
(
ptrayItem
->
hWnd
==
hWnd
)
{
if
(
ptrayItem
->
notifyIcon
.
hIcon
)
{
hdc
=
BeginPaint
(
hWnd
,
&
ps
);
GetClientRect
(
hWnd
,
&
rc
);
if
(
!
DrawIconEx
(
hdc
,
rc
.
left
+
ICON_BORDER
,
rc
.
top
+
ICON_BORDER
,
ptrayItem
->
notifyIcon
.
hIcon
,
ICON_SIZE
,
ICON_SIZE
,
0
,
0
,
DI_DEFAULTSIZE
|
DI_NORMAL
))
{
ERR
(
"Paint(SystrayWindow %p) failed -> removing SystrayItem %p
\n
"
,
hWnd
,
ptrayItem
);
SYSTRAY_Delete
(
&
ptrayItem
->
notifyIcon
);
}
}
break
;
}
ptrayItem
=
ptrayItem
->
nextTrayItem
;
}
EndPaint
(
hWnd
,
&
ps
);
}
break
;
case
WM_MOUSEMOVE
:
case
WM_LBUTTONDOWN
:
case
WM_LBUTTONUP
:
case
WM_RBUTTONDOWN
:
case
WM_RBUTTONUP
:
case
WM_MBUTTONDOWN
:
case
WM_MBUTTONUP
:
{
MSG
msg
;
SystrayItem
*
ptrayItem
=
systray
;
while
(
ptrayItem
)
{
if
(
ptrayItem
->
hWnd
==
hWnd
)
{
msg
.
hwnd
=
hWnd
;
msg
.
message
=
message
;
msg
.
wParam
=
wParam
;
msg
.
lParam
=
lParam
;
msg
.
time
=
GetMessageTime
();
msg
.
pt
.
x
=
LOWORD
(
GetMessagePos
());
msg
.
pt
.
y
=
HIWORD
(
GetMessagePos
());
SendMessageW
(
ptrayItem
->
hWndToolTip
,
TTM_RELAYEVENT
,
0
,
(
LPARAM
)
&
msg
);
}
ptrayItem
=
ptrayItem
->
nextTrayItem
;
}
}
/* fall through */
case
WM_LBUTTONDBLCLK
:
if
(
wait
==
WAIT_TIMEOUT
)
case
WM_RBUTTONDBLCLK
:
case
WM_MBUTTONDBLCLK
:
{
{
SystrayItem
*
ptrayItem
=
systray
;
ERR
(
"timeout waiting for %s to start
\n
"
,
debugstr_w
(
command_line
));
return
FALSE
;
while
(
ptrayItem
)
{
if
(
ptrayItem
->
hWnd
==
hWnd
)
{
if
(
ptrayItem
->
notifyIcon
.
hWnd
&&
ptrayItem
->
notifyIcon
.
uCallbackMessage
)
{
if
(
!
PostMessageW
(
ptrayItem
->
notifyIcon
.
hWnd
,
ptrayItem
->
notifyIcon
.
uCallbackMessage
,
(
WPARAM
)
ptrayItem
->
notifyIcon
.
uID
,
(
LPARAM
)
message
))
{
ERR
(
"PostMessage(SystrayWindow %p) failed -> removing SystrayItem %p
\n
"
,
hWnd
,
ptrayItem
);
SYSTRAY_Delete
(
&
ptrayItem
->
notifyIcon
);
}
}
break
;
}
ptrayItem
=
ptrayItem
->
nextTrayItem
;
}
}
break
;
default:
return
(
DefWindowProcW
(
hWnd
,
message
,
wParam
,
lParam
));
}
}
return
(
0
);
return
TRUE
;
}
}
/*************************************************************************
static
BOOL
SYSTRAY_RegisterClass
(
void
)
* Shell_NotifyIcon [SHELL32.296]
* Shell_NotifyIconA [SHELL32.297]
*/
BOOL
WINAPI
Shell_NotifyIconA
(
DWORD
dwMessage
,
PNOTIFYICONDATAA
pnid
)
{
{
WNDCLASSW
wc
;
NOTIFYICONDATAW
nidW
;
static
const
WCHAR
WineSystrayW
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'S'
,
'y'
,
's'
,
't'
,
'r'
,
'a'
,
'y'
,
0
};
wc
.
style
=
CS_SAVEBITS
|
CS_DBLCLKS
;
wc
.
lpfnWndProc
=
SYSTRAY_WndProc
;
wc
.
cbClsExtra
=
0
;
wc
.
cbWndExtra
=
0
;
wc
.
hInstance
=
0
;
wc
.
hIcon
=
0
;
wc
.
hCursor
=
LoadCursorW
(
0
,
(
LPWSTR
)
IDC_ARROW
);
wc
.
hbrBackground
=
(
HBRUSH
)(
COLOR_WINDOW
+
1
);
wc
.
lpszMenuName
=
NULL
;
wc
.
lpszClassName
=
WineSystrayW
;
if
(
!
RegisterClassW
(
&
wc
))
{
ERR
(
"RegisterClass(WineSystray) failed
\n
"
);
return
FALSE
;
}
return
TRUE
;
}
nidW
.
cbSize
=
sizeof
(
nidW
);
nidW
.
hWnd
=
pnid
->
hWnd
;
nidW
.
uID
=
pnid
->
uID
;
nidW
.
uFlags
=
pnid
->
uFlags
;
nidW
.
uCallbackMessage
=
pnid
->
uCallbackMessage
;
nidW
.
hIcon
=
pnid
->
hIcon
;
static
BOOL
SYSTRAY_ItemInit
(
SystrayItem
*
ptrayItem
)
/* szTip */
{
MultiByteToWideChar
(
CP_ACP
,
0
,
pnid
->
szTip
,
sizeof
(
pnid
->
szTip
),
nidW
.
szTip
,
sizeof
(
nidW
.
szTip
));
RECT
rect
;
static
const
WCHAR
WineSystrayW
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'S'
,
'y'
,
's'
,
't'
,
'r'
,
'a'
,
'y'
,
0
};
static
const
WCHAR
Wine_SystrayW
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'-'
,
'S'
,
'y'
,
's'
,
't'
,
'r'
,
'a'
,
'y'
,
0
};
/* Register the class if this is our first tray item. */
if
(
firstSystray
)
{
firstSystray
=
FALSE
;
if
(
!
SYSTRAY_RegisterClass
()
)
{
ERR
(
"RegisterClass(WineSystray) failed
\n
"
);
return
FALSE
;
}
}
/* Initialize the window size. */
nidW
.
dwState
=
pnid
->
dwState
;
rect
.
left
=
0
;
nidW
.
dwStateMask
=
pnid
->
dwStateMask
;
rect
.
top
=
0
;
rect
.
right
=
ICON_SIZE
+
2
*
ICON_BORDER
;
rect
.
bottom
=
ICON_SIZE
+
2
*
ICON_BORDER
;
ZeroMemory
(
ptrayItem
,
sizeof
(
SystrayItem
)
);
/* Create tray window for icon. */
ptrayItem
->
hWnd
=
CreateWindowExW
(
WS_EX_TRAYWINDOW
,
WineSystrayW
,
Wine_SystrayW
,
WS_VISIBLE
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
rect
.
right
-
rect
.
left
,
rect
.
bottom
-
rect
.
top
,
0
,
0
,
0
,
0
);
if
(
!
ptrayItem
->
hWnd
)
{
ERR
(
"CreateWindow(WineSystray) failed
\n
"
);
return
FALSE
;
}
/* Create tooltip for icon. */
/* szInfo */
ptrayItem
->
hWndToolTip
=
CreateWindowW
(
TOOLTIPS_CLASSW
,
NULL
,
TTS_ALWAYSTIP
,
MultiByteToWideChar
(
CP_ACP
,
0
,
pnid
->
szInfo
,
sizeof
(
pnid
->
szInfo
),
nidW
.
szInfo
,
sizeof
(
nidW
.
szInfo
));
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
ptrayItem
->
hWnd
,
0
,
0
,
0
);
if
(
!
ptrayItem
->
hWndToolTip
)
{
ERR
(
"CreateWindow(TOOLTIP) failed
\n
"
);
return
FALSE
;
}
return
TRUE
;
}
nidW
.
u
.
uTimeout
=
pnid
->
u
.
uTimeout
;
static
void
SYSTRAY_ItemSetMessage
(
SystrayItem
*
ptrayItem
,
UINT
uCallbackMessage
)
/* szInfoTitle */
{
MultiByteToWideChar
(
CP_ACP
,
0
,
pnid
->
szInfoTitle
,
sizeof
(
pnid
->
szInfoTitle
),
nidW
.
szInfoTitle
,
sizeof
(
nidW
.
szInfoTitle
));
ptrayItem
->
notifyIcon
.
uCallbackMessage
=
uCallbackMessage
;
}
nidW
.
dwInfoFlags
=
pnid
->
dwInfoFlags
;
static
void
SYSTRAY_ItemSetIcon
(
SystrayItem
*
ptrayItem
,
HICON
hIcon
)
return
Shell_NotifyIconW
(
dwMessage
,
&
nidW
);
{
if
(
ptrayItem
->
notifyIcon
.
hIcon
)
DestroyIcon
(
ptrayItem
->
notifyIcon
.
hIcon
);
ptrayItem
->
notifyIcon
.
hIcon
=
CopyIcon
(
hIcon
);
InvalidateRect
(
ptrayItem
->
hWnd
,
NULL
,
TRUE
);
}
}
/*************************************************************************
static
void
SYSTRAY_ItemSetTip
(
SystrayItem
*
ptrayItem
,
const
WCHAR
*
szTip
,
int
modify
)
* Shell_NotifyIconW [SHELL32.298]
*/
BOOL
WINAPI
Shell_NotifyIconW
(
DWORD
dwMessage
,
PNOTIFYICONDATAW
nid
)
{
{
TTTOOLINFOW
ti
;
HWND
tray
;
COPYDATASTRUCT
cds
;
lstrcpynW
(
ptrayItem
->
notifyIcon
.
szTip
,
szTip
,
sizeof
(
ptrayItem
->
notifyIcon
.
szTip
)
/
sizeof
(
WCHAR
));
ti
.
cbSize
=
sizeof
(
TTTOOLINFOW
);
ti
.
uFlags
=
0
;
ti
.
hwnd
=
ptrayItem
->
hWnd
;
ti
.
hinst
=
0
;
ti
.
uId
=
0
;
ti
.
lpszText
=
ptrayItem
->
notifyIcon
.
szTip
;
ti
.
rect
.
left
=
0
;
ti
.
rect
.
top
=
0
;
ti
.
rect
.
right
=
ICON_SIZE
+
2
*
ICON_BORDER
;
ti
.
rect
.
bottom
=
ICON_SIZE
+
2
*
ICON_BORDER
;
if
(
modify
)
SendMessageW
(
ptrayItem
->
hWndToolTip
,
TTM_UPDATETIPTEXTW
,
0
,
(
LPARAM
)
&
ti
);
else
SendMessageW
(
ptrayItem
->
hWndToolTip
,
TTM_ADDTOOLW
,
0
,
(
LPARAM
)
&
ti
);
}
TRACE
(
"dwMessage = %ld
\n
"
,
dwMessage
);
static
BOOL
SYSTRAY_Add
(
PNOTIFYICONDATAW
pnid
)
tray
=
FindWindowExW
(
0
,
NULL
,
classname
,
NULL
);
{
SystrayItem
**
ptrayItem
=
&
systray
;
static
const
WCHAR
emptyW
[]
=
{
0
};
/* Find last element. */
/* this isn't how native does it - it assumes that Explorer is always
while
(
*
ptrayItem
)
{
* running */
if
(
SYSTRAY_ItemIsEqual
(
pnid
,
&
(
*
ptrayItem
)
->
notifyIcon
)
)
if
(
!
tray
)
{
if
(
!
start_systray_process
())
return
FALSE
;
return
FALSE
;
ptrayItem
=
&
((
*
ptrayItem
)
->
nextTrayItem
);
tray
=
FindWindowExW
(
0
,
NULL
,
classname
,
NULL
);
}
}
/* Allocate SystrayItem for element and add to end of list. */
(
*
ptrayItem
)
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
SystrayItem
));
/* Initialize and set data for the tray element. */
SYSTRAY_ItemInit
(
(
*
ptrayItem
)
);
(
*
ptrayItem
)
->
notifyIcon
.
uID
=
pnid
->
uID
;
/* only needed for callback message */
(
*
ptrayItem
)
->
notifyIcon
.
hWnd
=
pnid
->
hWnd
;
/* only needed for callback message */
SYSTRAY_ItemSetIcon
(
*
ptrayItem
,
(
pnid
->
uFlags
&
NIF_ICON
)
?
pnid
->
hIcon
:
0
);
SYSTRAY_ItemSetMessage
(
*
ptrayItem
,
(
pnid
->
uFlags
&
NIF_MESSAGE
)
?
pnid
->
uCallbackMessage
:
0
);
SYSTRAY_ItemSetTip
(
*
ptrayItem
,
(
pnid
->
uFlags
&
NIF_TIP
)
?
pnid
->
szTip
:
emptyW
,
FALSE
);
TRACE
(
"%p: %p %s
\n
"
,
(
*
ptrayItem
),
(
*
ptrayItem
)
->
notifyIcon
.
hWnd
,
debugstr_w
((
*
ptrayItem
)
->
notifyIcon
.
szTip
));
return
TRUE
;
}
if
(
!
tray
)
return
FALSE
;
static
BOOL
SYSTRAY_Modify
(
PNOTIFYICONDATAW
pnid
)
cds
.
dwData
=
dwMessage
;
{
SystrayItem
*
ptrayItem
=
systray
;
/* FIXME: if statement only needed because we don't support interprocess
* icon handles */
while
(
ptrayItem
)
{
if
(
nid
->
uFlags
&
NIF_ICON
)
if
(
SYSTRAY_ItemIsEqual
(
pnid
,
&
ptrayItem
->
notifyIcon
)
)
{
{
if
(
pnid
->
uFlags
&
NIF_ICON
)
ICONINFO
iconinfo
;
SYSTRAY_ItemSetIcon
(
ptrayItem
,
pnid
->
hIcon
);
char
*
buffer
;
if
(
pnid
->
uFlags
&
NIF_MESSAGE
)
BITMAP
bmMask
;
SYSTRAY_ItemSetMessage
(
ptrayItem
,
pnid
->
uCallbackMessage
);
BITMAP
bmColour
;
if
(
pnid
->
uFlags
&
NIF_TIP
)
LONG
cbMaskBits
;
SYSTRAY_ItemSetTip
(
ptrayItem
,
pnid
->
szTip
,
TRUE
);
LONG
cbColourBits
;
TRACE
(
"%p: %p %s
\n
"
,
ptrayItem
,
ptrayItem
->
notifyIcon
.
hWnd
,
debugstr_w
(
ptrayItem
->
notifyIcon
.
szTip
));
if
(
!
GetIconInfo
(
nid
->
hIcon
,
&
iconinfo
))
return
TRUE
;
return
FALSE
;
}
ptrayItem
=
ptrayItem
->
nextTrayItem
;
if
(
!
GetObjectW
(
iconinfo
.
hbmMask
,
sizeof
(
bmMask
),
&
bmMask
)
||
!
GetObjectW
(
iconinfo
.
hbmColor
,
sizeof
(
bmColour
),
&
bmColour
))
{
DeleteObject
(
iconinfo
.
hbmMask
);
DeleteObject
(
iconinfo
.
hbmColor
);
return
FALSE
;
}
}
return
FALSE
;
/* not found */
}
cbMaskBits
=
(
bmMask
.
bmPlanes
*
bmMask
.
bmWidth
*
bmMask
.
bmHeight
*
bmMask
.
bmBitsPixel
)
/
8
;
cbColourBits
=
(
bmColour
.
bmPlanes
*
bmColour
.
bmWidth
*
bmColour
.
bmHeight
*
bmColour
.
bmBitsPixel
)
/
8
;
cds
.
cbData
=
sizeof
(
*
nid
)
+
2
*
sizeof
(
BITMAP
)
+
cbMaskBits
+
cbColourBits
;
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
cds
.
cbData
);
if
(
!
buffer
)
return
FALSE
;
cds
.
lpData
=
buffer
;
/*************************************************************************
memcpy
(
buffer
,
nid
,
sizeof
(
*
nid
));
*
buffer
+=
sizeof
(
*
nid
);
*/
memcpy
(
buffer
,
&
bmMask
,
sizeof
(
bmMask
));
BOOL
SYSTRAY_Init
(
void
)
buffer
+=
sizeof
(
bmMask
);
{
memcpy
(
buffer
,
&
bmColour
,
sizeof
(
bmColour
));
return
TRUE
;
buffer
+=
sizeof
(
bmColour
);
}
GetBitmapBits
(
iconinfo
.
hbmMask
,
cbMaskBits
,
buffer
);
buffer
+=
cbMaskBits
;
GetBitmapBits
(
iconinfo
.
hbmColor
,
cbColourBits
,
buffer
);
buffer
+=
cbColourBits
;
/*************************************************************************
DeleteObject
(
iconinfo
.
hbmMask
);
* Shell_NotifyIconW [SHELL32.298]
DeleteObject
(
iconinfo
.
hbmColor
);
*/
}
BOOL
WINAPI
Shell_NotifyIconW
(
DWORD
dwMessage
,
PNOTIFYICONDATAW
pnid
)
else
{
{
BOOL
flag
=
FALSE
;
cds
.
cbData
=
sizeof
(
*
nid
);
TRACE
(
"enter %p %d %ld
\n
"
,
pnid
->
hWnd
,
pnid
->
uID
,
dwMessage
);
cds
.
lpData
=
nid
;
switch
(
dwMessage
)
{
case
NIM_ADD
:
flag
=
SYSTRAY_Add
(
pnid
);
break
;
case
NIM_MODIFY
:
flag
=
SYSTRAY_Modify
(
pnid
);
break
;
case
NIM_DELETE
:
flag
=
SYSTRAY_Delete
(
pnid
);
break
;
}
}
TRACE
(
"leave %p %d %ld=%d
\n
"
,
pnid
->
hWnd
,
pnid
->
uID
,
dwMessage
,
flag
);
return
flag
;
}
/*************************************************************************
* Shell_NotifyIconA [SHELL32.297]
* Shell_NotifyIcon [SHELL32.296]
*/
BOOL
WINAPI
Shell_NotifyIconA
(
DWORD
dwMessage
,
PNOTIFYICONDATAA
pnid
)
{
BOOL
ret
;
PNOTIFYICONDATAW
p
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
NOTIFYICONDATAW
));
SendMessageW
(
tray
,
WM_COPYDATA
,
(
WPARAM
)
nid
->
hWnd
,
(
LPARAM
)
&
cds
);
memcpy
(
p
,
pnid
,
sizeof
(
NOTIFYICONDATAW
));
MultiByteToWideChar
(
CP_ACP
,
0
,
pnid
->
szTip
,
-
1
,
p
->
szTip
,
sizeof
(
p
->
szTip
)
/
sizeof
(
WCHAR
)
);
p
->
szTip
[
sizeof
(
p
->
szTip
)
/
sizeof
(
WCHAR
)
-
1
]
=
0
;
ret
=
Shell_NotifyIconW
(
dwMessage
,
p
);
/* FIXME: if statement only needed because we don't support interprocess
* icon handles */
if
(
nid
->
uFlags
&
NIF_ICON
)
HeapFree
(
GetProcessHeap
(),
0
,
cds
.
lpData
);
HeapFree
(
GetProcessHeap
(),
0
,
p
);
return
TRUE
;
return
ret
;
}
}
programs/explorer/Makefile.in
View file @
f689e3fc
...
@@ -4,10 +4,11 @@ SRCDIR = @srcdir@
...
@@ -4,10 +4,11 @@ SRCDIR = @srcdir@
VPATH
=
@srcdir@
VPATH
=
@srcdir@
MODULE
=
explorer.exe
MODULE
=
explorer.exe
APPMODE
=
-mwindows
APPMODE
=
-mwindows
IMPORTS
=
user32 kernel32
IMPORTS
=
user32
gdi32 advapi32
kernel32
C_SRCS
=
\
C_SRCS
=
\
explorer.c
explorer.c
\
systray.c
@MAKE_PROG_RULES@
@MAKE_PROG_RULES@
...
...
programs/explorer/explorer.c
View file @
f689e3fc
/*
/*
* explorer.exe
* explorer.exe
*
*
* Copyright 2004 CodeWeavers, Mike Hearn
* Copyright 2005,2006 CodeWeavers, Aric Stewart
* Copyright 2005,2006 CodeWeavers, Aric Stewart
*
*
* This library is free software; you can redistribute it and/or
* This library is free software; you can redistribute it and/or
...
@@ -21,8 +22,17 @@
...
@@ -21,8 +22,17 @@
#include <windows.h>
#include <windows.h>
#include <ctype.h>
#include <ctype.h>
#include <wine/debug.h>
#include <systray.h>
WINE_DEFAULT_DEBUG_CHANNEL
(
explorer
);
unsigned
int
shell_refs
=
0
;
typedef
struct
parametersTAG
{
typedef
struct
parametersTAG
{
BOOL
explorer_mode
;
BOOL
explorer_mode
;
BOOL
systray_mode
;
WCHAR
root
[
MAX_PATH
];
WCHAR
root
[
MAX_PATH
];
WCHAR
selection
[
MAX_PATH
];
WCHAR
selection
[
MAX_PATH
];
}
parameters_struct
;
}
parameters_struct
;
...
@@ -128,6 +138,11 @@ static void ParseCommandLine(LPSTR commandline,parameters_struct *parameters)
...
@@ -128,6 +138,11 @@ static void ParseCommandLine(LPSTR commandline,parameters_struct *parameters)
CopyPathRoot
(
parameters
->
root
,
CopyPathRoot
(
parameters
->
root
,
parameters
->
selection
);
parameters
->
selection
);
}
}
else
if
(
strncmp
(
p
,
"systray"
,
7
)
==
0
)
{
parameters
->
systray_mode
=
TRUE
;
p
+=
7
;
}
p2
=
p
;
p2
=
p
;
p
=
strchr
(
p
,
'/'
);
p
=
strchr
(
p
,
'/'
);
}
}
...
@@ -138,6 +153,44 @@ static void ParseCommandLine(LPSTR commandline,parameters_struct *parameters)
...
@@ -138,6 +153,44 @@ static void ParseCommandLine(LPSTR commandline,parameters_struct *parameters)
}
}
}
}
static
void
do_systray_loop
(
void
)
{
initialize_systray
();
while
(
TRUE
)
{
const
int
timeout
=
5
;
MSG
message
;
DWORD
res
;
res
=
MsgWaitForMultipleObjectsEx
(
0
,
NULL
,
shell_refs
?
INFINITE
:
timeout
*
1000
,
QS_ALLINPUT
,
MWMO_WAITALL
);
if
(
res
==
WAIT_TIMEOUT
)
break
;
res
=
PeekMessage
(
&
message
,
0
,
0
,
0
,
PM_REMOVE
);
if
(
!
res
)
continue
;
if
(
message
.
message
==
WM_QUIT
)
{
WINE_FIXME
(
"Somebody sent the shell a WM_QUIT message, should we reboot?"
);
/* Sending the tray window a WM_QUIT message is actually a
* tip given by some programming websites as a way of
* forcing a reboot! let's delay implementing this hack
* until we find a program that really needs it. for now
* just bail out.
*/
break
;
}
TranslateMessage
(
&
message
);
DispatchMessage
(
&
message
);
}
shutdown_systray
();
}
int
WINAPI
WinMain
(
HINSTANCE
hinstance
,
int
WINAPI
WinMain
(
HINSTANCE
hinstance
,
HINSTANCE
previnstance
,
HINSTANCE
previnstance
,
LPSTR
cmdline
,
LPSTR
cmdline
,
...
@@ -158,7 +211,12 @@ int WINAPI WinMain(HINSTANCE hinstance,
...
@@ -158,7 +211,12 @@ int WINAPI WinMain(HINSTANCE hinstance,
ParseCommandLine
(
cmdline
,
&
parameters
);
ParseCommandLine
(
cmdline
,
&
parameters
);
len
=
lstrlenW
(
winefile
)
+
1
;
len
=
lstrlenW
(
winefile
)
+
1
;
if
(
parameters
.
selection
[
0
])
if
(
parameters
.
systray_mode
)
{
do_systray_loop
();
return
0
;
}
else
if
(
parameters
.
selection
[
0
])
{
{
len
+=
lstrlenW
(
parameters
.
selection
)
+
2
;
len
+=
lstrlenW
(
parameters
.
selection
)
+
2
;
winefile_commandline
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
winefile_commandline
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
...
...
programs/explorer/systray.c
0 → 100644
View file @
f689e3fc
/*
* Copyright (C) 2004 Mike Hearn, for CodeWeavers
* Copyright (C) 2005 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* There are two types of window involved here. The first is the
* listener window. This is like the taskbar in Windows. It doesn't
* ever appear on-screen in our implementation, instead we create
* individual mini "adaptor" windows which are docked by the native
* systray host.
*
* In future for those who don't have a systray we could make the
* listener window more clever so it can draw itself like the Windows
* tray area does (with a clock and stuff).
*/
#include <assert.h>
#define UNICODE
#define _WIN32_IE 0x500
#include <windows.h>
#include <wine/debug.h>
#include <wine/list.h>
#include "systray.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
systray
);
const
static
WCHAR
adaptor_classname
[]
=
/* Adaptor */
{
'A'
,
'd'
,
'a'
,
'p'
,
't'
,
'o'
,
'r'
,
0
};
/* tray state */
struct
tray
{
HWND
window
;
struct
list
icons
;
};
/* an individual systray icon, unpacked from the NOTIFYICONDATA and always in unicode */
struct
icon
{
struct
list
entry
;
HICON
image
;
/* the image to render */
HWND
owner
;
/* the HWND passed in to the Shell_NotifyIcon call */
HWND
window
;
/* the adaptor window */
UINT
id
;
/* the unique id given by the app */
UINT
callback_message
;
};
static
struct
tray
tray
;
static
BOOL
hide_systray
;
/* adaptor code */
#define ICON_SIZE GetSystemMetrics(SM_CXSMICON)
/* space around icon (forces icon to center of KDE systray area) */
#define ICON_BORDER 4
static
LRESULT
WINAPI
adaptor_wndproc
(
HWND
window
,
UINT
msg
,
WPARAM
wparam
,
LPARAM
lparam
)
{
struct
icon
*
icon
=
NULL
;
BOOL
ret
;
WINE_TRACE
(
"hwnd=%p, msg=0x%x
\n
"
,
window
,
msg
);
/* set the icon data for the window from the data passed into CreateWindow */
if
(
msg
==
WM_NCCREATE
)
SetWindowLongPtrW
(
window
,
GWLP_USERDATA
,
(
LPARAM
)((
const
CREATESTRUCT
*
)
lparam
)
->
lpCreateParams
);
icon
=
(
struct
icon
*
)
GetWindowLongPtr
(
window
,
GWLP_USERDATA
);
switch
(
msg
)
{
case
WM_PAINT
:
{
RECT
rc
;
int
top
;
PAINTSTRUCT
ps
;
HDC
hdc
;
WINE_TRACE
(
"painting
\n
"
);
hdc
=
BeginPaint
(
window
,
&
ps
);
GetClientRect
(
window
,
&
rc
);
/* calculate top so we can deal with arbitrary sized trays */
top
=
((
rc
.
bottom
-
rc
.
top
)
/
2
)
-
((
ICON_SIZE
)
/
2
);
DrawIconEx
(
hdc
,
(
ICON_BORDER
/
2
),
top
,
icon
->
image
,
ICON_SIZE
,
ICON_SIZE
,
0
,
0
,
DI_DEFAULTSIZE
|
DI_NORMAL
);
EndPaint
(
window
,
&
ps
);
break
;
}
case
WM_MOUSEMOVE
:
case
WM_LBUTTONDOWN
:
case
WM_LBUTTONUP
:
case
WM_RBUTTONDOWN
:
case
WM_RBUTTONUP
:
case
WM_MBUTTONDOWN
:
case
WM_MBUTTONUP
:
case
WM_LBUTTONDBLCLK
:
case
WM_RBUTTONDBLCLK
:
case
WM_MBUTTONDBLCLK
:
{
/* notify the owner hwnd of the message */
WINE_TRACE
(
"relaying 0x%x
\n
"
,
msg
);
ret
=
PostMessage
(
icon
->
owner
,
icon
->
callback_message
,
(
WPARAM
)
icon
->
id
,
(
LPARAM
)
msg
);
if
(
!
ret
&&
(
GetLastError
()
==
ERROR_INVALID_HANDLE
))
{
WINE_ERR
(
"application window was destroyed without removing "
"notification icon, removing automatically
\n
"
);
DestroyWindow
(
window
);
}
return
0
;
}
case
WM_NCDESTROY
:
SetWindowLongPtr
(
window
,
GWLP_USERDATA
,
0
);
list_remove
(
&
icon
->
entry
);
DestroyIcon
(
icon
->
image
);
HeapFree
(
GetProcessHeap
(),
0
,
icon
);
shell_refs
--
;
WINE_TRACE
(
"shell now has %d refs
\n
"
,
shell_refs
);
break
;
}
return
DefWindowProc
(
window
,
msg
,
wparam
,
lparam
);
}
/* listener code */
static
struct
icon
*
get_icon
(
HWND
owner
,
UINT
id
)
{
struct
icon
*
this
;
/* search for the icon */
LIST_FOR_EACH_ENTRY
(
this
,
&
tray
.
icons
,
struct
icon
,
entry
)
if
((
this
->
id
==
id
)
&&
(
this
->
owner
=
owner
))
return
this
;
return
NULL
;
}
static
void
modify_icon
(
const
NOTIFYICONDATAW
*
nid
)
{
struct
icon
*
icon
;
WINE_TRACE
(
"id=0x%x, hwnd=%p
\n
"
,
nid
->
uID
,
nid
->
hWnd
);
/* demarshal the request from the NID */
icon
=
get_icon
(
nid
->
hWnd
,
nid
->
uID
);
if
(
!
icon
)
{
WINE_WARN
(
"Invalid icon ID (0x%x) for HWND %p
\n
"
,
nid
->
uID
,
nid
->
hWnd
);
return
;
}
if
(
nid
->
uFlags
&
NIF_ICON
)
{
if
(
icon
->
image
)
DestroyIcon
(
icon
->
image
);
icon
->
image
=
CopyIcon
(
nid
->
hIcon
);
RedrawWindow
(
icon
->
window
,
NULL
,
NULL
,
RDW_ERASE
|
RDW_INVALIDATE
|
RDW_UPDATENOW
);
}
if
(
nid
->
uFlags
&
NIF_MESSAGE
)
{
icon
->
callback_message
=
nid
->
uCallbackMessage
;
}
}
static
void
add_icon
(
const
NOTIFYICONDATAW
*
nid
)
{
RECT
rect
;
struct
icon
*
icon
;
const
static
WCHAR
adaptor_windowname
[]
=
/* Wine System Tray Adaptor */
{
'W'
,
'i'
,
'n'
,
'e'
,
' '
,
'S'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
' '
,
'T'
,
'r'
,
'a'
,
'y'
,
' '
,
'A'
,
'd'
,
'a'
,
'p'
,
't'
,
'o'
,
'r'
,
0
};
WINE_TRACE
(
"id=0x%x, hwnd=%p
\n
"
,
nid
->
uID
,
nid
->
hWnd
);
if
((
icon
=
get_icon
(
nid
->
hWnd
,
nid
->
uID
)))
{
WINE_WARN
(
"duplicate tray icon add, buggy app?
\n
"
);
return
;
}
if
(
!
(
icon
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
*
icon
))))
{
WINE_ERR
(
"out of memory
\n
"
);
return
;
}
icon
->
id
=
nid
->
uID
;
icon
->
owner
=
nid
->
hWnd
;
icon
->
image
=
NULL
;
rect
.
left
=
0
;
rect
.
top
=
0
;
rect
.
right
=
GetSystemMetrics
(
SM_CXSMICON
)
+
ICON_BORDER
;
rect
.
bottom
=
GetSystemMetrics
(
SM_CYSMICON
)
+
ICON_BORDER
;
AdjustWindowRect
(
&
rect
,
WS_CLIPSIBLINGS
|
WS_CAPTION
,
FALSE
);
/* create the adaptor window */
icon
->
window
=
CreateWindowEx
(
WS_EX_TRAYWINDOW
,
adaptor_classname
,
adaptor_windowname
,
WS_CLIPSIBLINGS
|
WS_CAPTION
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
rect
.
right
-
rect
.
left
,
rect
.
bottom
-
rect
.
top
,
NULL
,
NULL
,
NULL
,
icon
);
if
(
!
hide_systray
)
ShowWindow
(
icon
->
window
,
SW_SHOWNA
);
list_add_tail
(
&
tray
.
icons
,
&
icon
->
entry
);
modify_icon
(
nid
);
shell_refs
++
;
WINE_TRACE
(
"shell now has %d refs
\n
"
,
shell_refs
);
}
static
void
delete_icon
(
const
NOTIFYICONDATAW
*
nid
)
{
struct
icon
*
icon
=
get_icon
(
nid
->
hWnd
,
nid
->
uID
);
WINE_TRACE
(
"id=0x%x, hwnd=%p
\n
"
,
nid
->
uID
,
nid
->
hWnd
);
if
(
!
icon
)
{
WINE_ERR
(
"invalid tray icon ID specified: %ud
\n
"
,
nid
->
uID
);
return
;
}
DestroyWindow
(
icon
->
window
);
}
static
void
handle_incoming
(
HWND
hwndSource
,
COPYDATASTRUCT
*
cds
)
{
NOTIFYICONDATAW
nid
;
if
(
cds
->
cbData
<
sizeof
(
nid
))
return
;
memcpy
(
&
nid
,
cds
->
lpData
,
sizeof
(
nid
));
/* FIXME: if statement only needed because we don't support interprocess
* icon handles */
if
(
nid
.
uFlags
&
NIF_ICON
)
{
LONG
cbMaskBits
;
LONG
cbColourBits
;
BITMAP
bmMask
;
BITMAP
bmColour
;
const
char
*
buffer
=
cds
->
lpData
;
buffer
+=
sizeof
(
nid
);
if
(
cds
->
cbData
<
sizeof
(
nid
)
+
2
*
sizeof
(
BITMAP
))
{
WINE_ERR
(
"buffer underflow
\n
"
);
return
;
}
memcpy
(
&
bmMask
,
buffer
,
sizeof
(
bmMask
));
buffer
+=
sizeof
(
bmMask
);
memcpy
(
&
bmColour
,
buffer
,
sizeof
(
bmColour
));
buffer
+=
sizeof
(
bmColour
);
cbMaskBits
=
(
bmMask
.
bmPlanes
*
bmMask
.
bmWidth
*
bmMask
.
bmHeight
*
bmMask
.
bmBitsPixel
)
/
8
;
cbColourBits
=
(
bmColour
.
bmPlanes
*
bmColour
.
bmWidth
*
bmColour
.
bmHeight
*
bmColour
.
bmBitsPixel
)
/
8
;
if
(
cds
->
cbData
<
sizeof
(
nid
)
+
2
*
sizeof
(
BITMAP
)
+
cbMaskBits
+
cbColourBits
)
{
WINE_ERR
(
"buffer underflow
\n
"
);
return
;
}
/* sanity check */
if
((
bmColour
.
bmWidth
!=
bmMask
.
bmWidth
)
||
(
bmColour
.
bmHeight
!=
bmMask
.
bmHeight
))
{
WINE_ERR
(
"colour and mask bitmaps aren't consistent
\n
"
);
return
;
}
nid
.
hIcon
=
CreateIcon
(
NULL
,
bmColour
.
bmWidth
,
bmColour
.
bmHeight
,
bmColour
.
bmPlanes
,
bmColour
.
bmBitsPixel
,
buffer
,
buffer
+
cbMaskBits
);
}
switch
(
cds
->
dwData
)
{
case
NIM_ADD
:
add_icon
(
&
nid
);
break
;
case
NIM_DELETE
:
delete_icon
(
&
nid
);
break
;
case
NIM_MODIFY
:
modify_icon
(
&
nid
);
break
;
default:
WINE_FIXME
(
"unhandled tray message: %ld
\n
"
,
cds
->
dwData
);
break
;
}
/* FIXME: if statement only needed because we don't support interprocess
* icon handles */
if
(
nid
.
uFlags
&
NIF_ICON
)
DestroyIcon
(
nid
.
hIcon
);
}
static
LRESULT
WINAPI
listener_wndproc
(
HWND
window
,
UINT
msg
,
WPARAM
wparam
,
LPARAM
lparam
)
{
if
(
msg
==
WM_COPYDATA
)
handle_incoming
((
HWND
)
wparam
,
(
COPYDATASTRUCT
*
)
lparam
);
return
DefWindowProc
(
window
,
msg
,
wparam
,
lparam
);
}
static
BOOL
is_systray_hidden
(
void
)
{
const
WCHAR
hide_systray_keyname
[]
=
{
'S'
,
'o'
,
'f'
,
't'
,
'w'
,
'a'
,
'r'
,
'e'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'S'
,
'y'
,
's'
,
't'
,
'r'
,
'a'
,
'y'
,
0
};
const
WCHAR
hide_systray_valuename
[]
=
{
'H'
,
'i'
,
'd'
,
'd'
,
'e'
,
'n'
,
0
};
DWORD
hidden
;
HKEY
hkey
;
DWORD
size
;
DWORD
type
;
BOOL
ret
=
FALSE
;
/* @@ Wine registry key: HKCU\Software\Wine\Systray */
if
(
RegOpenKeyW
(
HKEY_CURRENT_USER
,
hide_systray_keyname
,
&
hkey
)
==
ERROR_SUCCESS
)
{
size
=
sizeof
(
hidden
);
if
(
RegQueryValueExW
(
hkey
,
hide_systray_valuename
,
0
,
&
type
,
(
LPBYTE
)
&
hidden
,
&
size
)
==
ERROR_SUCCESS
&&
type
==
REG_DWORD
)
{
if
(
hidden
!=
0
)
ret
=
TRUE
;
}
RegCloseKey
(
hkey
);
}
return
ret
;
}
/* this function creates the the listener window */
void
initialize_systray
(
void
)
{
WNDCLASSEX
class
;
HANDLE
event
;
static
const
WCHAR
classname
[]
=
/* Shell_TrayWnd */
{
'S'
,
'h'
,
'e'
,
'l'
,
'l'
,
'_'
,
'T'
,
'r'
,
'a'
,
'y'
,
'W'
,
'n'
,
'd'
,
0
};
static
const
WCHAR
winname
[]
=
/* Wine Systray Listener */
{
'W'
,
'i'
,
'n'
,
'e'
,
' '
,
'S'
,
'y'
,
's'
,
't'
,
'r'
,
'a'
,
'y'
,
' '
,
'L'
,
'i'
,
's'
,
't'
,
'e'
,
'n'
,
'e'
,
'r'
,
0
};
static
const
WCHAR
event_name
[]
=
{
'W'
,
'i'
,
'n'
,
'e'
,
'S'
,
'y'
,
's'
,
't'
,
'r'
,
'a'
,
'y'
,
'I'
,
'n'
,
'i'
,
't'
,
'e'
,
'd'
,
0
};
WINE_TRACE
(
"initiaizing
\n
"
);
hide_systray
=
is_systray_hidden
();
list_init
(
&
tray
.
icons
);
/* register the systray listener window class */
ZeroMemory
(
&
class
,
sizeof
(
class
));
class
.
cbSize
=
sizeof
(
class
);
class
.
lpfnWndProc
=
&
listener_wndproc
;
class
.
hInstance
=
NULL
;
class
.
hIcon
=
LoadIcon
(
0
,
IDI_WINLOGO
);
class
.
hCursor
=
LoadCursor
(
0
,
IDC_ARROW
);
class
.
hbrBackground
=
(
HBRUSH
)
COLOR_WINDOW
;
class
.
lpszClassName
=
(
WCHAR
*
)
&
classname
;
if
(
!
RegisterClassEx
(
&
class
))
{
WINE_ERR
(
"Could not register SysTray window class
\n
"
);
return
;
}
/* now register the adaptor window class */
ZeroMemory
(
&
class
,
sizeof
(
class
));
class
.
cbSize
=
sizeof
(
class
);
class
.
lpfnWndProc
=
adaptor_wndproc
;
class
.
hInstance
=
NULL
;
class
.
hIcon
=
LoadIcon
(
0
,
IDI_WINLOGO
);
class
.
hCursor
=
LoadCursor
(
0
,
IDC_ARROW
);
class
.
hbrBackground
=
(
HBRUSH
)
COLOR_WINDOW
;
class
.
lpszClassName
=
adaptor_classname
;
class
.
style
=
CS_SAVEBITS
|
CS_DBLCLKS
;
if
(
!
RegisterClassEx
(
&
class
))
{
WINE_ERR
(
"Could not register adaptor class
\n
"
);
return
;
}
tray
.
window
=
CreateWindow
(
classname
,
winname
,
WS_OVERLAPPED
,
CW_USEDEFAULT
,
CW_USEDEFAULT
,
0
,
0
,
0
,
0
,
0
,
0
);
if
(
!
tray
.
window
)
{
WINE_ERR
(
"Could not create tray window
\n
"
);
return
;
}
/* tell shell32 that we're ready */
event
=
OpenEventW
(
EVENT_MODIFY_STATE
,
FALSE
,
event_name
);
if
(
event
)
{
SetEvent
(
event
);
CloseHandle
(
event
);
}
}
void
shutdown_systray
(
void
)
{
DestroyWindow
(
tray
.
window
);
}
programs/explorer/systray.h
0 → 100644
View file @
f689e3fc
/*
* Copyright (C) 2004 Mike Hearn, for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
void
initialize_systray
(
void
);
void
shutdown_systray
(
void
);
/* when this drops to zero, a few seconds later the shell will shut down */
extern
unsigned
int
shell_refs
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment