Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
tray.c
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 316k
Category:
Windows Kernel
Development Platform:
Visual C++
- #include "cabinet.h"
- #include "cabwnd.h"
- #include "rcids.h"
- #include <shellapi.h>
- #include <shlapip.h>
- #include "trayclok.h"
- #include <fsmenu.h>
- #include <shguidp.h>
- #include "traynot.h"
- #include <help.h> // help ids
- #include <desktray.h>
- #if defined(FE_IME)
- #include <immp.h>
- #endif
- #include <trayp.h>
- #include <regstr.h>
- #ifdef WINNT
- // NT APM support
- #include <ntddapmt.h>
- #else
- // Win95 APM support
- #include <vmm.h>
- #include <bios.h>
- #define NOPOWERSTATUSDEFINES
- #include <pwrioctl.h>
- #include <wshioctl.h>
- #include <dbt.h>
- #include <pbt.h>
- #define Not_VxD
- #define No_CM_Calls
- #include <configmg.h>
- #endif
- #include "bandsite.h"
- #include "mmhelper.h" // Multimonitor helper functions
- #include <shdguid.h>
- #include "startmnu.h"
- #include "apithk.h"
- #include "uemapp.h"
- #include "deskconf.h"
- #define DM_FOCUS 0 // focus
- #define DM_SHUTDOWN TF_TRAY // shutdown
- #define DM_UEMTRACE TF_TRAY // timer service, other UEM stuff
- #define DM_MISC 0 // miscellany
- #define POLLINTERVAL (15*1000) // 15 seconds
- #define MINPOLLINTERVAL (3*1000) // 3 seconds
- #define ERRTIMEOUT (5*1000) // 5 seconds
- #define SECOND 1000
- #define RUNWAITSECS 5
- #define DOCKSTATE_DOCKED 0
- #define DOCKSTATE_UNDOCKED 1
- #define DOCKSTATE_UNKNOWN 2
- #ifdef WINNT
- #define MAXPRINTERBUFFER (MAX_PATH+18+1)
- #define JOB_STATUS_ERROR_BITS (JOB_STATUS_USER_INTERVENTION|JOB_STATUS_ERROR)
- #else
- #define MAXPRINTERBUFFER 32
- #define JOB_STATUS_ERROR_BITS JOB_STATUS_USER_INTERVENTION
- #endif
- #define RDM_ACTIVATE (WM_USER + 0x101)
- // import the WIN31 Compatibility HACKs from the shell32.dll
- WINSHELLAPI void WINAPI CheckWinIniForAssocs(void);
- HWND v_hwndDesktop = NULL;
- #ifdef WINNT
- // event to tell the services on NT5 that we are done with boot
- // and they can do their stuff
- HANDLE g_hShellReadyEvent = NULL;
- #endif
- UINT g_uStartButtonAllowPopup = WM_NULL;
- UINT g_uStartButtonBalloonTip = WM_NULL;
- // Users and Passwords must send this message to get the "real" logged on user to log off.
- // This is required since sometimes U&P runs in the context of a different user and logging this
- // other user off does no good. See extnetplwiz for the other half of this...-dsheldon.
- UINT g_uLogoffUser = WM_NULL;
- // DSA haPrinterNames structure:
- typedef struct _PRINTERNAME {
- TCHAR szPrinterName[MAXPRINTERBUFFER]; // we know max printer name length is 32
- LPITEMIDLIST pidlPrinter; // relative pidl to printer
- BOOL fInErrorState;
- } PRINTERNAME, * LPPRINTERNAME;
- void RaiseDesktop();
- void PrintNotify_Init(HWND hwnd);
- void PrintNotify_AddToQueue(LPHANDLE phaPrinterNames, LPSHELLFOLDER *ppsf, LPCITEMIDLIST pidlPrinter);
- BOOL PrintNotify_StartThread(HWND hwnd);
- void PrintNotify_HandleFSNotify(HWND hwnd, LPCITEMIDLIST *ppidl, LONG lEvent);
- void PrintNotify_Exit(void);
- void PrintNotify_IconNotify(HWND hwnd, LPARAM uMsg);
- void RevertMenu(HMENU hmenuSub, UINT idMenu);
- void _PropagateMessage(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
- void Tray_HandleShellServiceObject(WPARAM wParam, LPARAM lParam);
- STDMETHODIMP CShellTray_AddViewPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lParam);
- HMONITOR Tray_GetDisplayRectFromRect(LPRECT prcDisplay, LPCRECT prcIn, UINT uFlags);
- HMONITOR Tray_GetDisplayRectFromPoint(LPRECT prcDisplay, POINT pt, UINT uFlags);
- void Tray_MakeStuckRect(LPRECT prcStick, LPCRECT prcBound, SIZE size, UINT uStick);
- void Tray_ScreenSizeChange(HWND hwnd);
- void Tray_SizeWindows();
- void Tray_ContextMenu(DWORD dwPos, BOOL fSetTime);
- void Tray_DesktopMenu(DWORD dwPos);
- void StuckAppChange(HWND hwnd, LPCRECT prcOld, LPCRECT prcNew, BOOL bTray);
- void Tray_StuckTrayChange();
- void SetWindowStyleBit(HWND hwnd, DWORD dwBit, DWORD dwValue);
- void CStartDropTarget_Register();
- void CStartDropTarget_Revoke();
- void DestroySavedWindowPositions(LPWINDOWPOSITIONS pPositions);
- void Tray_ResetZorder();
- void Cabinet_InitGlobalMetrics(WPARAM, LPTSTR);
- void StartMenuFolder_ContextMenu(DWORD dwPos);
- void Tray_HandleSize();
- void Tray_HandleSizing(WPARAM code, LPRECT lprc, UINT uStuckPlace);
- void MinimizeAll(HWND hwndView);
- void Tray_RegisterGlobalHotkeys();
- void Tray_UnregisterGlobalHotkeys();
- void Tray_HandleGlobalHotkey(WPARAM wParam);
- void Tray_Unhide();
- void Tray_SetAutoHideTimer();
- void Tray_ComputeHiddenRect(LPRECT prc, UINT uStuck);
- UINT Tray_GetDockedRect(LPRECT prc, BOOL fMoving);
- void Tray_CalcClipCoords(RECT *prcClip, const RECT *prcMonitor, const RECT *prcNew);
- void Tray_ClipInternal(const RECT *prcClip);
- void Tray_ClipWindow(BOOL fEnableClipping);
- UINT Tray_CalcDragPlace(POINT pt);
- UINT Tray_RecalcStuckPos(LPRECT prc);
- void Tray_AutoHideCollision();
- void StartMenu_Build();
- int HotkeyList_Restore(HWND hwnd);
- LRESULT Tray_RegisterHotkey(HWND hwnd, int i);
- void RecordStartButtonSize(HWND hwndStart);
- LRESULT Tray_HandleMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmi);
- void Tray_OnDesktopState(LPARAM lParam);
- #ifdef DESKBTN
- void Tray_CreateDesktopButton();
- HWND g_hwndDesktopTB = NULL;
- #else
- #define Tray_CreateDesktopButton() 0
- #define KillConfigDesktopDlg() 0
- #define g_hwndDesktopTB NULL
- #endif
- void ToggleDesktop();
- void LowerDesktop();
- void DoTrayProperties(INT nStartPage);
- void RunStartupApps();
- void ClearRecentDocumentsAndMRUStuff(BOOL fBroadcastChange);
- void WriteCleanShutdown(DWORD dwValue);
- void RefreshStartMenu();
- // Review chrisny: this can be moved into an object easily to handle generic droptarget, dropcursor
- // , autoscrool, etc. . .
- void _DragEnter(HWND hwndTarget, const POINTL ptStart, IDataObject *pdtObject);
- void _DragMove(HWND hwndTarget, const POINTL ptStart);
- BOOL SetWindowZorder(HWND hwnd, HWND hwndInsertAfter);
- //
- // Settings UI entry point types.
- //
- typedef VOID (WINAPI *PTRAYPROPSHEETCALLBACK)(DWORD nStartPage);
- typedef VOID (WINAPI *PSETTINGSUIENTRY)(PTRAYPROPSHEETCALLBACK);
- DWORD SettingsUI_ThreadProc(void *pv);
- VOID WINAPI SettingsUI_TrayPropSheetCallback(DWORD nStartPage);
- extern void Cabinet_RefreshAll(void);
- #if defined(DBCS) || defined(FE_IME)
- // b#11258-win95d
- #if !defined(WINNT)
- DWORD WINAPI ImmGetAppIMECompatFlags(DWORD dwThreadID);
- #endif
- #endif
- // Shell perf automation
- extern DWORD g_dwShellStartTime;
- extern DWORD g_dwShellStopTime;
- // appbar stuff
- BOOL IAppBarSetAutoHideBar(HWND hwnd, BOOL fAutoHide, UINT uEdge);
- void IAppBarActivationChange(HWND hwnd, UINT uEdge);
- HWND AppBarGetAutoHideBar(UINT uEdge);
- // BOGUS: nuke this (multiple monitors...)
- HWND g_hwndAutoHide[ABE_MAX] = { NULL, NULL, NULL, NULL };
- extern BOOL g_fUseMerge;
- BOOL IsChildOrHWND(HWND hwnd, HWND hwndChild)
- {
- return (hwnd == hwndChild || IsChild(hwnd, hwndChild));
- }
- void ClockCtl_HandleTrayHide(BOOL fHiding)
- {
- g_ts.fLastHandleTrayHide = fHiding ? TRUE : FALSE;
- SendMessage(g_ts.hwndNotify, TNM_TRAYHIDE, 0, fHiding);
- }
- // dyna-res change for multi-config hot/warm-doc
- void HandleDisplayChange(int x, int y, BOOL fCritical);
- #ifdef WINNT
- #define IsDisplayChangeSafe() TRUE
- #else
- BOOL IsDisplayChangeSafe(void);
- #endif
- DWORD GetMinDisplayRes(void);
- // appbar stuff
- void AppBarNotifyAll(HMONITOR hmon, UINT uMsg, HWND hwndExclude, LPARAM lParam);
- // Button subclass.
- WNDPROC g_ButtonProc = NULL;
- // timer IDs
- #define IDT_AUTOHIDE 2
- #define IDT_AUTOUNHIDE 3
- #ifdef DELAYWININICHANGE
- #define IDT_DELAYWININICHANGE 5
- #endif
- #define IDT_DESKTOP 6
- #define IDT_PROGRAMS IDM_PROGRAMS
- #define IDT_RECENT IDM_RECENT
- #define IDT_REBUILDMENU 7
- #define IDT_HANDLEDELAYBOOTSTUFF 8
- #define IDT_REVERTPROGRAMS 9
- #define IDT_REVERTRECENT 10
- #define IDT_REVERTFAVORITES 11
- #define IDT_STARTMENU 12
- #define IDT_ENDUNHIDEONTRAYNOTIFY 13
- #define IDT_SERVICE0 14
- #define IDT_SERVICE1 15
- #define IDT_SERVICELAST IDT_SERVICE1
- #define IDT_SAVESETTINGS 17
- #define IDT_ENABLEUNDO 18
- #define RECTWIDTH(rc) ((rc).right-(rc).left)
- #define RECTHEIGHT(rc) ((rc).bottom-(rc).top)
- #define SZ_RECENTKEY TEXT("Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs\Menu")
- #define SZ_STARTMENUKEY TEXT("Software\Microsoft\Windows\CurrentVersion\Explorer\Start Menu\Menu")
- #define REGSTR_EXPLORER_ADVANCED REGSTR_PATH_EXPLORER TEXT("\Advanced")
- int g_cyTrayBorders = -1; // the amount of Y difference between the window and client height;
- //
- // amount of time to show/hide the tray
- // to turn sliding off set these to 0
- //
- int g_dtSlideHide;
- int g_dtSlideShow;
- typedef enum
- {
- // Sequence commands
- SMCT_NONE = 0x0,
- SMCT_PRIMARY = 0x1,
- SMCT_WININIASSOCS = 0x2,
- SMCT_DESKTOPHOTKEYS = 0x3,
- SMCT_INITPROGRAMS = 0x4,
- SMCT_INITRECENT = 0x5,
- SMCT_INITFAVORITES = 0x6,
- SMCT_PARTFILLPROGRAMS = 0x7,
- SMCT_FILLRECENT = 0x8,
- SMCT_FILLPROGRAMS = 0x9,
- SMCT_FILLFASTITEMS = 0xa,
- SMCT_FILLFAVORITES = 0xb,
- SMCT_BUILDLISTOFPATHS = 0xc, // Must be last item in list before SMCT_DONE
- SMCT_DONE = 0xd,
- // Single execution commands
- SMCT_FILLRECENTONLY = 0xe,
- SMCT_FILLPROGRAMSONLY = 0xf,
- SMCT_DESKTOPHOTKEYSONLY = 0x10,
- SMCT_FILLFAVORITESONLY = 0x11,
- SMCT_STOP = 0x12,
- SMCT_RESTART = 0x13,
- SMCT_STOPNOWAITBLOP = 0x14, // Stop, but don't wait for BuildListOfPaths to complete
- } STARTMENUCONTROLTHREAD;
- // INSTRUMENTATION WARNING: If you change anything here, make sure to update instrument.c
- // we need to start at 500 because we're now sharing the hotkey handler
- // with shortcuts.. they use an index array so they need to be 0 based
- // NOTE, this constant is also in desktop.cpp, so that we can forward hotkeys from the desktop for
- // NOTE, app compatibility.
- #define GHID_FIRST 500
- enum
- {
- GHID_RUN = GHID_FIRST,
- GHID_MINIMIZEALL,
- GHID_UNMINIMIZEALL,
- GHID_HELP,
- GHID_EXPLORER,
- GHID_FINDFILES,
- GHID_FINDCOMPUTER,
- GHID_TASKTAB,
- GHID_TASKSHIFTTAB,
- GHID_SYSPROPERTIES,
- GHID_DESKTOP,
- GHID_MAX
- };
- const DWORD GlobalKeylist[] =
- { MAKELONG(TEXT('R'), MOD_WIN),
- MAKELONG(TEXT('M'), MOD_WIN),
- MAKELONG(TEXT('M'), MOD_SHIFT|MOD_WIN),
- MAKELONG(VK_F1,MOD_WIN),
- MAKELONG(TEXT('E'),MOD_WIN),
- MAKELONG(TEXT('F'),MOD_WIN),
- MAKELONG(TEXT('F'), MOD_CONTROL|MOD_WIN),
- MAKELONG(VK_TAB, MOD_WIN),
- MAKELONG(VK_TAB, MOD_WIN|MOD_SHIFT),
- MAKELONG(VK_PAUSE,MOD_WIN),
- MAKELONG(TEXT('D'),MOD_WIN),
- };
- void DoExitWindows(HWND hwnd);
- void Tray_Command(UINT idCmd);
- LONG Tray_SetAutoHideState(BOOL fAutoHide);
- LRESULT CALLBACK Tray_WndProc(HWND, UINT, WPARAM, LPARAM);
- //---------------------------------------------------------------------------
- // Global to this file only.
- // NB None of the tray stuff needs thread serialising because
- // we only ever have one tray.
- TRAYSTUFF g_ts = {0};
- // g_fDockingFlags bits
- #define DOCKFLAG_WARMEJECTABLENOW (1<<0)
- // TVSD Flags.
- #define TVSD_NULL 0x0000
- #define TVSD_AUTOHIDE 0x0001
- #define TVSD_TOPMOST 0x0002
- #define TVSD_SMSMALLICONS 0x0004
- #define TVSD_HIDECLOCK 0x0008
- #define TVSD_SHOWDESKBTN 0x0010
- // old Win95 TVSD struct
- typedef struct _TVSD95
- {
- DWORD dwSize;
- LONG cxScreen;
- LONG cyScreen;
- LONG dxLeft;
- LONG dxRight;
- LONG dyTop;
- LONG dyBottom;
- DWORD uAutoHide;
- RECTL rcAutoHide;
- DWORD uStuckPlace;
- DWORD dwFlags;
- } TVSD95;
- // Nashville tray save data
- typedef struct _TVSD
- {
- DWORD dwSize;
- LONG lSignature; // signature (must be negative)
- DWORD dwFlags; // TVSD_ flags
- DWORD uStuckPlace; // current stuck edge
- SIZE sStuckWidths; // widths of stuck rects (BUGBUG: in tbd units)
- RECT rcLastStuck; // last stuck position in pixels
- } TVSD;
- // convenient union for reading either
- typedef union _TVSDCOMPAT
- {
- TVSD; // new format
- TVSD95 w95; // old format
- } TVSDCOMPAT;
- #define TVSDSIG_CURRENT (-1L)
- #define IS_CURRENT_TVSD(t) ((t.dwSize >= sizeof(TVSD)) && (t.lSignature < 0))
- #define MAYBE_WIN95_TVSD(t) (t.dwSize == sizeof(TVSD95))
- BOOL ShouldWeShowTheStartButtonBalloon()
- {
- DWORD dwType;
- DWORD dwData = 0;
- DWORD cbSize = sizeof(DWORD);
- SHGetValue(HKEY_CURRENT_USER, REGSTR_EXPLORER_ADVANCED,
- TEXT("StartButtonBalloonTip"), &dwType, (BYTE*)&dwData, &cbSize);
- return (dwData == 0); // if StartButtonBalloonTip == 1, don't show
- }
- void DontShowTheStartButtonBalloonAnyMore()
- {
- DWORD dwData = 1;
- SHSetValue(HKEY_CURRENT_USER, REGSTR_EXPLORER_ADVANCED,
- TEXT("StartButtonBalloonTip"), REG_DWORD, (BYTE*)&dwData, sizeof(DWORD));
- }
- void DestroyStartButtonBalloon()
- {
- if (g_ts.hwndStartBalloon)
- {
- DestroyWindow(g_ts.hwndStartBalloon);
- g_ts.hwndStartBalloon = NULL;
- }
- }
- void ShowStartButtonToolTip()
- {
- if (!ShouldWeShowTheStartButtonBalloon())
- return;
- if (!g_ts.hwndStartBalloon)
- {
- g_ts.hwndStartBalloon = CreateWindow(TOOLTIPS_CLASS, NULL,
- WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP | TTS_BALLOON,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL, hinstCabinet,
- NULL);
- if (g_ts.hwndStartBalloon)
- {
- // set the version so we can have non buggy mouse event forwarding
- SendMessage(g_ts.hwndStartBalloon, CCM_SETVERSION, COMCTL32_VERSION, 0);
- SendMessage(g_ts.hwndStartBalloon, TTM_SETMAXTIPWIDTH, 0, (LPARAM)300);
- }
- }
- if (g_ts.hwndStartBalloon)
- {
- TCHAR szTip[MAX_PATH];
- szTip[0] = TEXT('');
- LoadString(hinstCabinet, IDS_STARTMENUBALLOON_TIP, szTip, ARRAYSIZE(szTip));
- if (szTip[0])
- {
- RECT rc;
- TOOLINFO ti = {0};
- ti.cbSize = SIZEOF(ti);
- ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_TRANSPARENT;
- ti.hwnd = v_hwndTray;
- ti.uId = (UINT_PTR)g_ts.hwndStart;
- //ti.lpszText = NULL;
- SendMessage(g_ts.hwndStartBalloon, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
- SendMessage(g_ts.hwndStartBalloon, TTM_TRACKACTIVATE, (WPARAM)FALSE, (LPARAM)0);
- ti.lpszText = szTip;
- SendMessage(g_ts.hwndStartBalloon, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
- LoadString(hinstCabinet, IDS_STARTMENUBALLOON_TITLE, szTip, ARRAYSIZE(szTip));
- if (szTip[0])
- {
- SendMessage(g_ts.hwndStartBalloon, TTM_SETTITLE, TTI_INFO, (LPARAM)szTip);
- }
- GetWindowRect(g_ts.hwndStart, &rc);
- SendMessage(g_ts.hwndStartBalloon, TTM_TRACKPOSITION, 0, MAKELONG((rc.left + rc.right)/2, rc.top));
- SetWindowZorder(g_ts.hwndStartBalloon, HWND_TOPMOST);
- SendMessage(g_ts.hwndStartBalloon, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&ti);
- }
- }
- }
- // Mirror a bitmap in a DC (mainly a text object in a DC)
- //
- // [samera]
- //
- void MirrorBitmapInDC( HDC hdc , HBITMAP hbmOrig )
- {
- HDC hdcMem;
- HBITMAP hbm;
- BITMAP bm;
- if( !GetObject( hbmOrig , sizeof(BITMAP) , &bm ))
- return;
- hdcMem = CreateCompatibleDC( hdc );
- if( !hdcMem )
- return;
- hbm = CreateCompatibleBitmap( hdc , bm.bmWidth , bm.bmHeight );
- if( !hbm )
- {
- DeleteDC( hdcMem );
- return;
- }
- //
- // Flip the bitmap
- //
- SelectObject( hdcMem , hbm );
- SET_DC_RTL_MIRRORED(hdcMem);
- BitBlt( hdcMem , 0 , 0 , bm.bmWidth , bm.bmHeight ,
- hdc , 0 , 0 , SRCCOPY );
- SET_DC_LAYOUT(hdcMem,0);
- //
- // BUGBUG : The offset by 1 in hdcMem is to solve the off-by-one problem. Removed.
- // [samera]
- //
- BitBlt( hdc , 0 , 0 , bm.bmWidth , bm.bmHeight ,
- hdcMem , 0 , 0 , SRCCOPY );
- DeleteDC( hdcMem );
- DeleteObject( hbm );
- return;
- }
- BOOL Tray_CreateClockWindow()
- {
- g_ts.hwndNotify = TrayNotifyCreate(v_hwndTray, IDC_CLOCK, hinstCabinet);
- return BOOLFROMPTR(g_ts.hwndNotify);
- }
- BOOL InitTrayClass(HINSTANCE hInstance)
- {
- WNDCLASS wc;
- ZeroMemory(&wc, SIZEOF(WNDCLASS));
- wc.lpszClassName = TEXT(WNDCLASS_TRAYNOTIFY);
- wc.style = CS_DBLCLKS;
- wc.lpfnWndProc = Tray_WndProc;
- wc.hInstance = hInstance;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
- return RegisterClass(&wc);
- }
- HMENU LoadMenuPopup(LPCTSTR id)
- {
- HMENU hMenuSub = NULL;
- HMENU hMenu = LoadMenu(hinstCabinet, id);
- if (hMenu) {
- hMenuSub = GetSubMenu(hMenu, 0);
- if (hMenuSub) {
- RemoveMenu(hMenu, 0, MF_BYPOSITION);
- }
- DestroyMenu(hMenu);
- }
- return hMenuSub;
- }
- #define CXGAP 4
- //----------------------------------------------------------------------------
- // Compose the Start bitmap out of a flag and some text.
- // REVIEW UNDONE - Put the up/down arrow back in.
- HBITMAP CreateStartBitmap(HWND hwndTray)
- {
- HBITMAP hbmpStart = NULL;
- HBITMAP hbmpStartOld = NULL;
- HICON hiconFlag = NULL;
- int cx, cy, cySmIcon;
- TCHAR szStart[256];
- SIZE size;
- HDC hdcStart;
- HDC hdcScreen;
- HFONT hfontStart = NULL;
- HFONT hfontStartOld = NULL;
- NONCLIENTMETRICS ncm;
- RECT rcStart;
- WORD wLang;
- // DebugMsg(DM_TRACE, "c.csb: Creating start bitmap.");
- hdcScreen = GetDC(NULL);
- hdcStart = CreateCompatibleDC(hdcScreen);
- if (hdcStart)
- {
- ncm.cbSize = SIZEOF(ncm);
- if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, SIZEOF(ncm), &ncm, FALSE))
- {
- wLang = GetUserDefaultLangID();
- // Select normal weight font for chinese language.
- if ( PRIMARYLANGID(wLang) == LANG_CHINESE &&
- ( (SUBLANGID(wLang) == SUBLANG_CHINESE_TRADITIONAL) ||
- (SUBLANGID(wLang) == SUBLANG_CHINESE_SIMPLIFIED) ))
- ncm.lfCaptionFont.lfWeight = FW_NORMAL;
- else
- ncm.lfCaptionFont.lfWeight = FW_BOLD;
- hfontStart = CreateFontIndirect(&ncm.lfCaptionFont);
- }
- else
- {
- DebugMsg(DM_ERROR, TEXT("c.csb: Can't create font."));
- }
- // Get an idea about how big we need everyhting to be.
- LoadString(hinstCabinet, IDS_START, szStart, ARRAYSIZE(szStart));
- hfontStartOld = SelectObject(hdcScreen, hfontStart);
- GetTextExtentPoint(hdcScreen, szStart, lstrlen(szStart), &size);
- SelectObject(hdcScreen, hfontStartOld);
- // Mimick the tray and ignore the font size for determining the height.
- #if 0
- cy = max(g_cySize, size.cy);
- #else
- cy = g_cySize;
- #endif
- cySmIcon = GetSystemMetrics(SM_CYSMICON);
- cx = (cy + size.cx) + CXGAP;
- hbmpStart = CreateCompatibleBitmap(hdcScreen, cx, cy);
- hbmpStartOld = SelectObject(hdcStart, hbmpStart);
- hfontStartOld = SelectObject(hdcStart , hfontStart);
- //
- // Let's mirror the DC, so that text won't get mirrored
- // if the window ir mirrored
- //
- if (IS_WINDOW_RTL_MIRRORED(hwndTray))
- {
- //
- // Mirror the DC, so that drawing goes from the visual right
- // edge. [samera]
- //
- SET_DC_RTL_MIRRORED(hdcStart);
- }
- rcStart.left = -g_cxEdge; // subtract this off because drawcaptiontemp adds it on
- rcStart.top = 0;
- rcStart.right = cx;
- rcStart.bottom = cy;
- hiconFlag = (HICON)LoadImage(NULL, MAKEINTRESOURCE(OIC_WINLOGO_DEFAULT ), IMAGE_ICON, cySmIcon, cySmIcon, 0);
- // Get User to draw everything for us.
- DrawCaptionTemp(hwndTray, hdcStart, &rcStart, hfontStart, hiconFlag, szStart, DC_INBUTTON | DC_TEXT | DC_ICON | DC_NOSENDMSG);
- //
- // Now we have the image ready to maintained by USER, let's mirror
- // it so that when it is bitblt'ed to the hwndTray DC it will be mirrored
- // and the bitmap image is maintained. [samera]
- //
- if (IS_WINDOW_RTL_MIRRORED(hwndTray))
- {
- MirrorBitmapInDC(hdcStart, hbmpStart);
- }
- // Clean up Start stuff.
- SelectObject(hdcStart, hbmpStartOld);
- if (hfontStart)
- {
- SelectObject(hdcStart, hfontStartOld);
- DeleteObject(hfontStart);
- }
- DeleteDC(hdcStart);
- DestroyIcon(hiconFlag);
- }
- else
- {
- DebugMsg(DM_ERROR, TEXT("c.csb: Can't create Start bitmap."));
- }
- ReleaseDC(NULL, hdcScreen);
- return hbmpStart;
- }
- // Set the stuck monitor for the tray window
- void Tray_SetStuckMonitor()
- {
- // use STICK_LEFT because most of the multi-monitors systems are set up
- // side by side. use DEFAULTTONULL because we don't want to get the wrong one
- // use the center point to call again in case we failed the first time.
- g_ts.hmonStuck = MonitorFromRect(&g_ts.arStuckRects[STICK_LEFT],
- MONITOR_DEFAULTTONULL);
- if (!g_ts.hmonStuck)
- {
- POINT pt;
- pt.x = (g_ts.arStuckRects[STICK_LEFT].left + g_ts.arStuckRects[STICK_LEFT].right)/2;
- pt.y = (g_ts.arStuckRects[STICK_LEFT].top + g_ts.arStuckRects[STICK_LEFT].bottom)/2;
- g_ts.hmonStuck = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
- }
- g_ts.hmonOld = g_ts.hmonStuck;
- }
- VOID Tray_GetSaveStateAndInitRects()
- {
- TVSDCOMPAT tvsd;
- DWORD cbData1, cbData2;
- RECT rcDisplay;
- DWORD dwTrayFlags;
- UINT uStick;
- SIZE size;
- //
- // first fill in the defaults
- //
- SetRect(&rcDisplay, 0, 0, g_cxPrimaryDisplay, g_cyPrimaryDisplay);
- // size gets defaults
- size.cx = g_ts.sizeStart.cx + 2 * (g_cxDlgFrame + g_cxBorder);
- size.cy = g_ts.sizeStart.cy + 2 * (g_cyDlgFrame + g_cyBorder);
- // sStuckWidths gets minimum
- g_ts.sStuckWidths.cx = 2 * (g_cxDlgFrame + g_cxBorder);
- g_ts.sStuckWidths.cy = g_ts.sizeStart.cy + 2 * (g_cyDlgFrame + g_cyBorder);
- g_ts.uStuckPlace = STICK_BOTTOM;
- dwTrayFlags = TVSD_TOPMOST;
- #ifdef WINNT
- // if we are on a remote hydra session
- // and if there is no previous saved value,
- // do not display the clock.
- if (IsRemoteSession())
- {
- g_ts.fHideClock = TRUE;
- dwTrayFlags |= TVSD_HIDECLOCK;
- }
- #endif
- g_ts.uAutoHide = 0;
- //
- // now try to load saved vaules
- //
- // BUG : 231077
- // Since Tasbar properties don't roam from NT5 to NT4, (NT4 -> NT5 yes)
- // Allow roaming from NT4 to NT5 only for the first time the User logs
- // on to NT5, so that future changes to NT5 are not lost when the user
- // logs on to NT4 after customizing the taskbar properties on NT5.
- cbData1 = SIZEOF(tvsd);
- cbData2 = SIZEOF(tvsd);
- if (Reg_GetStruct(g_hkeyExplorer, TEXT("StuckRects2"), TEXT("Settings"),
- &tvsd, &cbData1)
- ||
- Reg_GetStruct(g_hkeyExplorer, TEXT("StuckRects"), TEXT("Settings"),
- &tvsd, &cbData2))
- {
- if (IS_CURRENT_TVSD(tvsd) && IsValidSTUCKPLACE(tvsd.uStuckPlace))
- {
- Tray_GetDisplayRectFromRect(&rcDisplay, &tvsd.rcLastStuck,
- MONITOR_DEFAULTTONEAREST);
- // BUGBUG: scale sStuckWidths.cy here?
- size = tvsd.sStuckWidths;
- g_ts.uStuckPlace = tvsd.uStuckPlace;
- dwTrayFlags = tvsd.dwFlags;
- }
- else if (MAYBE_WIN95_TVSD(tvsd) &&
- IsValidSTUCKPLACE(tvsd.w95.uStuckPlace))
- {
- g_ts.uStuckPlace = tvsd.w95.uStuckPlace;
- dwTrayFlags = tvsd.w95.dwFlags;
- if (tvsd.w95.uAutoHide & AH_ON)
- dwTrayFlags |= TVSD_AUTOHIDE;
- switch (g_ts.uStuckPlace)
- {
- case STICK_LEFT:
- size.cx = tvsd.w95.dxLeft;
- break;
- case STICK_RIGHT:
- size.cx = tvsd.w95.dxRight;
- break;
- case STICK_BOTTOM:
- size.cy = tvsd.w95.dyBottom;
- break;
- case STICK_TOP:
- size.cy = tvsd.w95.dyTop;
- break;
- }
- }
- }
- ASSERT(IsValidSTUCKPLACE(g_ts.uStuckPlace));
- //
- // use the size only if it is not bogus
- //
- if (g_ts.sStuckWidths.cx < size.cx)
- g_ts.sStuckWidths.cx = size.cx;
- if (g_ts.sStuckWidths.cy < size.cy)
- g_ts.sStuckWidths.cy = size.cy;
- //
- // set the tray flags
- //
- g_ts.fAlwaysOnTop = dwTrayFlags & TVSD_TOPMOST ? 1 : 0;
- g_ts.fSMSmallIcons = dwTrayFlags & TVSD_SMSMALLICONS ? 1 : 0;
- g_ts.fHideClock = dwTrayFlags & TVSD_HIDECLOCK ? 1 : 0;
- g_ts.uAutoHide = dwTrayFlags & TVSD_AUTOHIDE ? (AH_ON | AH_HIDING) : 0;
- g_ts.fShowDeskBtn = dwTrayFlags & TVSD_SHOWDESKBTN ? 1 : 0;
- //
- // initialize stuck rects
- //
- for (uStick = STICK_LEFT; uStick <= STICK_BOTTOM; uStick++)
- Tray_MakeStuckRect(&g_ts.arStuckRects[uStick], &rcDisplay, g_ts.sStuckWidths, uStick);
- // Determine which monitor the tray is on using its stuck rectangles
- Tray_SetStuckMonitor();
- }
- extern HRESULT Tray_SaveView();
- void _SaveTrayStuff(void)
- {
- TVSD tvsd;
- tvsd.dwSize = SIZEOF(tvsd);
- tvsd.lSignature = TVSDSIG_CURRENT;
- // position
- CopyRect(&tvsd.rcLastStuck, &g_ts.arStuckRects[g_ts.uStuckPlace]);
- tvsd.sStuckWidths = g_ts.sStuckWidths;
- tvsd.uStuckPlace = g_ts.uStuckPlace;
- tvsd.dwFlags = 0;
- if (g_ts.fAlwaysOnTop) tvsd.dwFlags |= TVSD_TOPMOST;
- if (g_ts.fSMSmallIcons) tvsd.dwFlags |= TVSD_SMSMALLICONS;
- if (g_ts.fHideClock) tvsd.dwFlags |= TVSD_HIDECLOCK;
- if (g_ts.uAutoHide & AH_ON) tvsd.dwFlags |= TVSD_AUTOHIDE;
- if (g_ts.fShowDeskBtn) tvsd.dwFlags |= TVSD_SHOWDESKBTN;
- // Save for now in Stuck rects.
- // BUGBUG: really want to save rcLastStuck per user/maching/config
- Reg_SetStruct(g_hkeyExplorer, TEXT("StuckRects2"), TEXT("Settings"), &tvsd, SIZEOF(tvsd));
- Tray_SaveView(g_ts.ptbs);
- return;
- }
- /*------------------------------------------------------------------
- ** align toolbar so that buttons are flush with client area
- ** and make toolbar's buttons to be MENU style
- **------------------------------------------------------------------*/
- void Tray_AlignStartButton()
- {
- HWND hwndStart = g_ts.hwndStart;
- if (hwndStart)
- {
- RECT rcClient;
- if (g_ts.sizeStart.cy == 0)
- {
- BITMAP bm;
- HBITMAP hbm = (HBITMAP)SendMessage(hwndStart, BM_GETIMAGE, IMAGE_BITMAP, 0);
- if (hbm)
- {
- GetObject(hbm, SIZEOF(bm), &bm);
- g_ts.sizeStart.cx = bm.bmWidth + 2 * g_cxEdge;
- g_ts.sizeStart.cy = bm.bmHeight + 2 * g_cyEdge;
- if (g_ts.sizeStart.cy < g_cySize + 2*g_cyEdge)
- g_ts.sizeStart.cy = g_cySize + 2*g_cyEdge;
- }
- else
- {
- // BUGBUG: New user may have caused this to fail...
- // Setup some size for it that wont be too bad...
- g_ts.sizeStart.cx = g_cxMinimized;
- g_ts.sizeStart.cy = g_cySize + 2*g_cyEdge;
- }
- }
- GetClientRect(g_ts.hwndMain, &rcClient);
- SetWindowPos(hwndStart, NULL, 0, 0, (rcClient.right < g_ts.sizeStart.cx) ? rcClient.right : g_ts.sizeStart.cx, g_ts.sizeStart. cy, SWP_NOZORDER | SWP_NOACTIVATE);
- }
- }
- //----------------------------------------------------------------------------
- // Allow us to do stuff on a "button-down".
- HWND g_hwndPrevFocus = NULL;
- LRESULT CALLBACK StartButtonSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- LRESULT lRet;
- static UINT uDown = 0;
- static BOOL fAllowUp = FALSE; // Is the start button allowed to be in the up position?
- ASSERT(g_ButtonProc)
- // Is the button going down?
- if (uMsg == BM_SETSTATE)
- {
- // Is it going Down?
- if (wParam) {
- // DebugMsg(DM_TRACE, "c.stswp: Set state %d", wParam);
- // Yes, Is it already down?
- if (!uDown)
- {
- // Nope.
- INSTRUMENT_STATECHANGE(SHCNFI_STATE_START_DOWN);
- uDown = 1;
- // If we are going down, then we do not want to popup again until the Start Menu is collapsed
- fAllowUp = FALSE;
- SendMessage(g_ts.hwndTrayTips, TTM_ACTIVATE, FALSE, 0L);
- // Show the button down.
- lRet = CallWindowProc(g_ButtonProc, hwnd, uMsg, wParam, lParam );
- // Notify the parent.
- SendMessage(GetParent(hwnd), WM_COMMAND, (WPARAM)LOWORD(GetDlgCtrlID(hwnd)), (LPARAM)hwnd);
- return lRet;
- }
- else
- {
- // Yep. Do nothing.
- // fDown = FALSE;
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
- }
- else
- {
- // DebugMsg(DM_TRACE, "c.stswp: Set state %d", wParam);
- // Nope, buttons coming up.
- // Is it supposed to be down? Is it not allowed to be up?
- if (uDown == 1 || !fAllowUp)
- {
- INSTRUMENT_STATECHANGE(SHCNFI_STATE_START_UP);
- // Yep, do nothing.
- uDown = 2;
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
- else
- {
- SendMessage(g_ts.hwndTrayTips, TTM_ACTIVATE, TRUE, 0L);
- // Nope, Forward it on.
- uDown = 0;
- return CallWindowProc(g_ButtonProc, hwnd, uMsg, wParam, lParam );
- }
- }
- }
- else
- {
- switch (uMsg) {
- case WM_LBUTTONDOWN:
- // The button was clicked on, then we don't need no stink'n focus rect.
- SendMessage(GetParent(hwnd), WM_UPDATEUISTATE, MAKEWPARAM(UIS_SET,
- UISF_HIDEFOCUS), 0);
- goto ProcessCapture;
- break;
- case WM_KEYDOWN:
- // The user pressed enter or return or some other bogus key combination when
- // the start button had keyboard focus, so show the rect....
- SendMessage(GetParent(hwnd), WM_UPDATEUISTATE, MAKEWPARAM(UIS_CLEAR,
- UISF_HIDEFOCUS), 0);
- if (wParam == VK_RETURN)
- PostMessage(g_ts.hwndMain, WM_COMMAND, IDC_KBSTART, 0);
- // We do not need the capture, because we do all of our button processing
- // on the button down. In fact taking capture for no good reason screws with
- // drag and drop into the menus. We're overriding user.
- ProcessCapture:
- lRet = CallWindowProc(g_ButtonProc, hwnd, uMsg, wParam, lParam );
- SetCapture(NULL);
- return lRet;
- break;
- case WM_MOUSEMOVE:
- {
- MSG msg;
- msg.lParam = lParam;
- msg.wParam = wParam;
- msg.message = uMsg;
- msg.hwnd = hwnd;
- SendMessage(g_ts.hwndTrayTips, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)& msg);
- break;
- }
- case WM_NULL:
- break;
- default:
- if (uMsg == g_uStartButtonAllowPopup)
- {
- fAllowUp = TRUE;
- }
- break;
- }
- return CallWindowProc(g_ButtonProc, hwnd, uMsg, wParam, lParam);
- }
- }
- const TCHAR c_szButton[] = TEXT("button");
- /*------------------------------------------------------------------
- ** create the toolbar with the three buttons and align windows
- **------------------------------------------------------------------*/
- HWND Tray_CreateStartButton()
- {
- HWND hwnd;
- DWORD dwStyle = BS_BITMAP;
- g_uStartButtonBalloonTip = RegisterWindowMessage(TEXT("Welcome Finished"));
- g_uLogoffUser = RegisterWindowMessage(TEXT("Logoff User"));
- // BUGBUG: BS_CENTER | VS_VCENTER required, user bug?
- hwnd = CreateWindowEx(0, c_szButton, NULL,
- WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
- BS_PUSHBUTTON | BS_LEFT | BS_VCENTER | dwStyle,
- 0, 0, 0, 0, v_hwndTray, (HMENU)IDC_START, hinstCabinet, NULL);
- if (hwnd)
- {
- // Subclass it.
- g_ts.hwndStart = hwnd;
- g_ButtonProc = SubclassWindow(hwnd, StartButtonSubclassWndProc);
- {
- HBITMAP hbm = CreateStartBitmap(v_hwndTray);
- if (hbm)
- {
- SendMessage(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm);
- Tray_AlignStartButton();
- return hwnd;
- }
- }
- DestroyWindow(hwnd);
- }
- return NULL;
- }
- void Tray_GetWindowSizes(PRECT prcClient, PRECT prcView, PRECT prcClock, PRECT prcDesktop)
- {
- int xFSView, yFSView, cxFSView, cyFSView;
- int xClock, yClock, cxClock, cyClock;
- DWORD_PTR dwClockMinSize;
- int cxDesktop;
- int cyDesktop;
- BOOL fDesktopBottom = FALSE;
- RECT rcDesktop;
- if (!g_hwndDesktopTB || !g_ts.fShowDeskBtn || SHRestricted(REST_CLASSICSHELL))
- {
- cxDesktop = cyDesktop = 0;
- }
- else
- {
- SendMessage(g_hwndDesktopTB, TB_GETITEMRECT, 0, (LPARAM)&rcDesktop);
- cxDesktop = RECTWIDTH(rcDesktop) + g_cxEdge;
- cyDesktop = RECTHEIGHT(rcDesktop);
- }
- // size to fill either horizontally or vertically
- if ((prcClient->right - g_ts.sizeStart.cx) > (prcClient->bottom - g_ts.sizeStart.cy))
- {
- //
- // Horizontal - Two cases. One where we have room below the
- // toolbar to display the clock. so display it there, else
- // display it on the right hand side...
- //
- yFSView = 0;
- cyFSView = prcClient->bottom - yFSView;
- // Recalc the min size for horizontal arrangement
- dwClockMinSize = SendMessage(g_ts.hwndNotify, WM_CALCMINSIZE,
- 0x7fff, prcClient->bottom);
- cxClock = LOWORD(dwClockMinSize);
- cyClock = HIWORD(dwClockMinSize);
- // xClock = prcClient->right - cxClock - g_cxFrame; // A little gap...
- xClock = prcClient->right - cxClock - cxDesktop;
- #ifdef VCENTER_CLOCK
- yClock = (prcClient->bottom-cyClock)/2; // Center it vertically.
- #else
- yClock = 0;
- #endif
- xFSView = g_ts.sizeStart.cx + g_cxFrame + 1; // NT5 VFREEZE: one more pixel here
- cxFSView = xClock - xFSView - g_cxFrame/2; // NT5 VFREEZE: we removed the right etch, so reclaim the space
- }
- else
- {
- // Vertical - Again two cases. One where we have room to the
- // right to display the clock. Note: we want some gap here between
- // the clock and toolbar. If it does not fit, then we will center
- // it at the bottom...
- xFSView = 0;
- cxFSView = prcClient->right - xFSView;
- dwClockMinSize = SendMessage(g_ts.hwndNotify, WM_CALCMINSIZE,
- 0x7fff, g_ts.sizeStart.cy);
- cxClock = LOWORD(dwClockMinSize);
- cyClock = HIWORD(dwClockMinSize);
- if ((g_ts.sizeStart.cx + cxClock + 4 * g_cyTabSpace + cxDesktop) < prcClient->right)
- {
- int cyMax = g_ts.sizeStart.cy;;
- // Can fit on the same row!
- xClock = prcClient->right - cxClock - (2 * g_cxEdge) - cxDesktop; // A little gap...
- yClock = 0;
- if (cyClock > cyMax)
- cyMax = cyClock;
- yFSView = cyMax + g_cyTabSpace;
- cyFSView = prcClient->bottom - yFSView;
- }
- else
- {
- // Nope put at bottom
- // Recalc the min size for vertical arrangement
- dwClockMinSize = SendMessage(g_ts.hwndNotify, WM_CALCMINSIZE,
- cxFSView, 0x7fff);
- if (LOWORD(dwClockMinSize) + cyDesktop >= prcClient->right)
- fDesktopBottom = TRUE;
- if (fDesktopBottom) {
- cxClock = min(LOWORD(dwClockMinSize), prcClient->right);
- } else {
- cxClock = LOWORD(dwClockMinSize);
- }
- cyClock = HIWORD(dwClockMinSize);
- xClock = (prcClient->right - cxClock) / 2;
- yClock = prcClient->bottom - cyClock - g_cyTabSpace;
- // if we'ren ot slowing the clock, we still need to make
- // room for hte desktop button
- if (!cyClock)
- yClock -= (cyDesktop - g_cyEdge);
- if (fDesktopBottom) {
- yClock -= cyDesktop;
- } else {
- xClock -= (cxDesktop/2);
- }
- yFSView = g_ts.sizeStart.cy + g_cyTabSpace;
- cyFSView = yClock - yFSView - g_cyTabSpace;
- }
- }
- prcView->left = xFSView;
- prcView->top = yFSView;
- prcView->right = xFSView + cxFSView;
- prcView->bottom = yFSView + cyFSView;
- prcClock->left = xClock;
- prcClock->top = yClock;
- prcClock->right = xClock + cxClock;
- prcClock->bottom = yClock + cyClock;
- if (fDesktopBottom) {
- prcDesktop->top = prcClock->bottom + g_cyEdge;
- prcDesktop->left = (prcClient->right - cxDesktop)/2;
- } else {
- *prcDesktop = *prcClock;
- prcDesktop->left = prcClock->right + g_cxEdge;
- }
- prcDesktop->bottom = prcDesktop->top + cyDesktop;
- prcDesktop->right = prcDesktop->left + cxDesktop + g_cxEdge;
- }
- void Tray_RestoreWindowPos()
- {
- WINDOWPLACEMENT wp;
- //first restore the stuck postitions
- Tray_GetSaveStateAndInitRects();
- wp.length = SIZEOF(wp);
- wp.showCmd = SW_HIDE;
- g_ts.uMoveStuckPlace = (UINT)-1;
- Tray_GetDockedRect(&wp.rcNormalPosition, FALSE);
- ClockCtl_HandleTrayHide(g_ts.fHideClock);
- SetWindowPlacement(v_hwndTray, &wp);
- }
- //----------------------------------------------------------------------------
- // Sort of a registry equivalent of the profile API's.
- BOOL Reg_GetStruct(HKEY hkey, LPCTSTR pszSubKey, LPCTSTR pszValue, void *pData, DWORD *pcbData)
- {
- BOOL fRet = FALSE;
- if (!g_fCleanBoot)
- {
- fRet = ERROR_SUCCESS == SHGetValue(hkey, pszSubKey, pszValue, NULL, pData, pcbData);
- }
- return fRet;
- }
- //----------------------------------------------------------------------------
- // Sort of a registry equivalent of the profile API's.
- BOOL Reg_SetStruct(HKEY hkey, LPCTSTR pszSubKey, LPCTSTR pszValue, void *lpData, DWORD cbData)
- {
- HKEY hkeyNew = hkey;
- BOOL fRet = FALSE;
- if (pszSubKey)
- {
- if (RegCreateKey(hkey, pszSubKey, &hkeyNew) != ERROR_SUCCESS)
- {
- return fRet;
- }
- }
- if (RegSetValueEx(hkeyNew, pszValue, 0, REG_BINARY, lpData, cbData) == ERROR_SUCCESS)
- {
- fRet = TRUE;
- }
- if (pszSubKey)
- RegCloseKey(hkeyNew);
- return fRet;
- }
- //----------------------------------------------------------------------------
- // Get the display (monitor) rectangle from the given arbitrary point
- HMONITOR Tray_GetDisplayRectFromPoint(LPRECT prcDisplay, POINT pt, UINT uFlags)
- {
- HMONITOR hmon;
- RECT rcEmpty = {0};
- hmon = MonitorFromPoint(pt, uFlags);
- if (hmon && prcDisplay)
- GetMonitorRect(hmon, prcDisplay);
- else if (prcDisplay)
- *prcDisplay = rcEmpty;
- return hmon;
- }
- //----------------------------------------------------------------------------
- // Get the display (monitor) rectangle from the given arbitrary rectangle
- HMONITOR Tray_GetDisplayRectFromRect(LPRECT prcDisplay, LPCRECT prcIn,
- UINT uFlags)
- {
- HMONITOR hmon;
- RECT rcEmpty = {0};
- hmon = MonitorFromRect(prcIn, uFlags);
- if (hmon && prcDisplay)
- GetMonitorRect(hmon, prcDisplay);
- else if (prcDisplay)
- *prcDisplay = rcEmpty;
- return hmon;
- }
- //----------------------------------------------------------------------------
- // Get the display (monitor) rectangle where the taskbar is currently on,
- // if that monitor is invalid, get the nearest one.
- void Tray_GetStuckDisplayRect(UINT uStuckPlace, LPRECT prcDisplay)
- {
- BOOL fValid;
- ASSERT(prcDisplay);
- fValid = GetMonitorRect(g_ts.hmonStuck, prcDisplay);
- if (!fValid)
- Tray_GetDisplayRectFromRect(prcDisplay, &g_ts.arStuckRects[uStuckPlace], MONITOR_DEFAULTTONEAREST);
- }
- //----------------------------------------------------------------------------
- // Snap a StuckRect to the edge of a containing rectangle
- // fClip determines whether to clip the rectangle if it's off the display or move it onto the screen
- void Tray_MakeStuckRect(LPRECT prcStick, LPCRECT prcBound, SIZE size,
- UINT uStick)
- {
- CopyRect(prcStick, prcBound);
- InflateRect(prcStick, g_cxEdge, g_cyEdge);
- if (size.cx < 0) size.cx *= -1;
- if (size.cy < 0) size.cy *= -1;
- switch (uStick)
- {
- case STICK_LEFT: prcStick->right = (prcStick->left + size.cx); break;
- case STICK_TOP: prcStick->bottom = (prcStick->top + size.cy); break;
- case STICK_RIGHT: prcStick->left = (prcStick->right - size.cx); break;
- case STICK_BOTTOM: prcStick->top = (prcStick->bottom - size.cy); break;
- }
- }
- /*-------------------------------------------------------------------
- ** the screen size has changed, so the docked rectangles need to be
- ** adjusted to the new screen.
- **-------------------------------------------------------------------*/
- void ResizeStuckRects(RECT *arStuckRects)
- {
- UINT uStick;
- RECT rcDisplay;
- Tray_GetStuckDisplayRect(g_ts.uStuckPlace, &rcDisplay);
- for (uStick = STICK_LEFT; uStick <= STICK_BOTTOM; uStick++)
- Tray_MakeStuckRect(&arStuckRects[uStick], &rcDisplay, g_ts.sStuckWidths, uStick);
- }
- void Tray_UpdateDockingFlags()
- {
- #ifndef WINNT
- BOOL fIoSuccess;
- BIOSPARAMS bp;
- DWORD cbOut;
- #endif
- static BOOL fFirstTime=TRUE;
- if ((!fFirstTime) && (g_ts.hBIOS == INVALID_HANDLE_VALUE)) {
- return;
- }
- #ifdef WINNT
- g_ts.hBIOS = INVALID_HANDLE_VALUE;
- fFirstTime = FALSE;
- return;
- #else
- g_ts.hBIOS = CreateFile(TEXT("\\.\BIOS"),
- GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, 0, NULL);
- if (g_ts.hBIOS == INVALID_HANDLE_VALUE) {
- fFirstTime = FALSE;
- return;
- }
- bp.bp_ret=0;
- fIoSuccess=DeviceIoControl(
- g_ts.hBIOS,
- PNPBIOS_SERVICE_GETDOCKCAPABILITIES,
- &bp,
- SIZEOF(bp),
- &bp,
- SIZEOF(bp),
- &cbOut,
- NULL);
- if (fFirstTime) {
- // first time through, if a warm dock change is not possible,
- // don't bother with the menu item.
- fFirstTime=FALSE;
- if (!fIoSuccess) {
- // problem getting the dock capabilities:
- // if problem wasn't "undocked now" or "can't identify dock"
- // then warm ejecting isn't possible.
- if ((bp.bp_ret!=PNPBIOS_ERR_SYSTEM_NOT_DOCKED) &&
- (bp.bp_ret!=PNPBIOS_ERR_CANT_DETERMINE_DOCKING)) {
- CloseHandle(g_ts.hBIOS);
- g_ts.hBIOS=INVALID_HANDLE_VALUE;
- return;
- }
- } else {
- // success getting the dock capabilities:
- // if the dock isn't capable of warm or hot docking
- // then warm ejecting isn't possible
- if (!(bp.bp_ret&PNPBIOS_DOCK_CAPABILITY_TEMPERATURE)) {
- CloseHandle(g_ts.hBIOS);
- g_ts.hBIOS=INVALID_HANDLE_VALUE;
- return;
- }
- }
- }
- // on each call we update WARMEJECTABLENOW
- // depending on whether the dock is capable of warm ejecting right now
- if ((fIoSuccess) && (bp.bp_ret&PNPBIOS_DOCK_CAPABILITY_TEMPERATURE)) {
- g_ts.fDockingFlags|=DOCKFLAG_WARMEJECTABLENOW;
- } else {
- g_ts.fDockingFlags&=~DOCKFLAG_WARMEJECTABLENOW;
- }
- return;
- #endif
- }
- /* Check if system is currently in a docking station.
- *
- * Returns: TRUE if docked, FALSE if undocked or can't tell.
- *
- */
- // BUGBUG (lamadio): This should be moved into it's own file with the other
- // API and ACPI routines.
- BOOL GetDockedState(void)
- {
- #ifndef WINNT // BUGBUG - Fix this when NT gets docking capability
- struct _ghwpi { // Get_Hardware_Profile_Info parameter blk
- CMAPI cmApi;
- ULONG ulIndex;
- PFARHWPROFILEINFO pHWProfileInfo;
- ULONG ulFlags;
- HWPROFILEINFO HWProfileInfo;
- } *pghwpi;
- HANDLE hCMHeap;
- UINT Result = DOCKSTATE_UNKNOWN;
- DWORD dwRecipients = BSM_VXDS;
- #define HEAP_SHARED 0x04000000 /* put heap in shared memory--undoc'd */
- // Create a shared heap for CONFIGMG parameters
- if ((hCMHeap = HeapCreate(HEAP_SHARED, 1, 4096)) == NULL)
- return DOCKSTATE_UNKNOWN;
- #undef HEAP_SHARED
- // Allocate parameter block in shared memory
- pghwpi = (struct _ghwpi *)HeapAlloc(hCMHeap, HEAP_ZERO_MEMORY,
- SIZEOF(*pghwpi));
- if (pghwpi == NULL)
- {
- HeapDestroy(hCMHeap);
- return DOCKSTATE_UNKNOWN;
- }
- pghwpi->cmApi.dwCMAPIRet = 0;
- pghwpi->cmApi.dwCMAPIService = GetVxDServiceOrdinal(_CONFIGMG_Get_Hardware_Profile_Info);
- pghwpi->cmApi.pCMAPIStack = (DWORD)(((LPBYTE)pghwpi) + SIZEOF(pghwpi->cmApi));
- pghwpi->ulIndex = 0xFFFFFFFF;
- pghwpi->pHWProfileInfo = &pghwpi->HWProfileInfo;
- pghwpi->ulFlags = 0;
- // "Call" _CONFIGMG_Get_Hardware_Profile_Info service
- BroadcastSystemMessage(0, &dwRecipients, WM_DEVICECHANGE, DBT_CONFIGMGAPI32,
- (LPARAM)pghwpi);
- if (pghwpi->cmApi.dwCMAPIRet == CR_SUCCESS) {
- switch (pghwpi->HWProfileInfo.HWPI_dwFlags) {
- case CM_HWPI_DOCKED:
- Result = DOCKSTATE_DOCKED;
- break;
- case CM_HWPI_UNDOCKED:
- Result = DOCKSTATE_UNDOCKED;
- break;
- default:
- Result = DOCKSTATE_UNKNOWN;
- break;
- }
- }
- HeapDestroy(hCMHeap);
- return Result;
- #else
- return(DOCKSTATE_DOCKED);
- #endif
- }
- int g_cHided;
- #ifdef DEBUG
- BOOL g_dbNoShow;
- #endif
- void Tray_Hide();
- //*** TrayShowWindow -- temporary 'invisible' un-autohide
- // DESCRIPTION
- // various tray resize routines need the tray to be un-autohide'd for
- // stuff to be calculated correctly. so we un-autohide it (invisibly...)
- // here. note the WM_SETREDRAW to prevent flicker (nt5:182340).
- // note that this is kind of a hack -- ideally the tray code would do
- // stuff correctly even if hidden.
- // NOTES
- // separate routine (vs. inline) to aid debugging. turn this func off
- // to 'see' resize stuff happening
- // BUGBUG what happens if rehide kicks off before we're done?
- void TrayShowWindow(int nCmdShow)
- {
- if (nCmdShow == SW_HIDE) {
- if (g_cHided++ == 0) {
- #ifdef DEBUG
- if (!g_dbNoShow)
- #endif
- SendMessage(v_hwndTray, WM_SETREDRAW, FALSE, 0);
- ShowWindow(v_hwndTray, nCmdShow);
- Tray_Unhide();
- }
- }
- else if (nCmdShow == SW_SHOWNA) {
- ASSERT(g_cHided > 0); // must be push/pop
- if (--g_cHided == 0) {
- Tray_Hide();
- #ifdef DEBUG
- if (!g_dbNoShow)
- #endif
- ShowWindow(v_hwndTray, nCmdShow);
- SendMessage(v_hwndTray, WM_SETREDRAW, TRUE, 0);
- }
- }
- else {
- ASSERT(0);
- }
- return;
- }
- void Tray_VerifySize(BOOL fWinIni)
- {
- RECT rc;
- BOOL fHiding;
- fHiding = (g_ts.uAutoHide & AH_HIDING);
- if (fHiding) {
- // force it visible so various calculations will happen relative
- // to unhidden size/position.
- //
- // fixes (e.g.) ie5:154536, where dropping a large-icon ISFBand
- // onto hidden tray didn't do size negotiation.
- //
- // BUGBUG what happens if rehide kicks off before we're done?.
- TrayShowWindow(SW_HIDE);
- }
- rc = g_ts.arStuckRects[g_ts.uStuckPlace];
- Tray_HandleSizing(0, NULL, g_ts.uStuckPlace);
- //
- // if the old view had a height, and now it won't...
- // push it up to at least one height
- //
- // do this only on win ini if we're on the top or bottom
- if (fWinIni && STUCK_HORIZONTAL(g_ts.uStuckPlace)) {
- RECT rcView;
- // stash the old view size;
- GetClientRect(g_ts.hwndView, &rcView);
- if (RECTHEIGHT(rcView) && (RECTHEIGHT(rc) == g_cyTrayBorders)) {
- int cyOneRow = g_cySize + 2 * g_cyEdge;
- if (g_ts.uStuckPlace == STICK_TOP) {
- rc.bottom = rc.top + cyOneRow;
- } else {
- rc.top = rc.bottom - cyOneRow;
- }
- // now snap this size.
- Tray_HandleSizing(0, NULL, g_ts.uStuckPlace);
- }
- }
- if (!EqualRect(&rc, &g_ts.arStuckRects[g_ts.uStuckPlace]))
- {
- if (fWinIni) {
- // if we're changing size or position, we need to be unhidden
- Tray_Unhide();
- Tray_SizeWindows();
- }
- rc = g_ts.arStuckRects[g_ts.uStuckPlace];
- if ((g_ts.uAutoHide & (AH_ON | AH_HIDING)) != (AH_ON | AH_HIDING))
- {
- g_ts.fSelfSizing = TRUE;
- SetWindowPos(g_ts.hwndMain, NULL,
- rc.left, rc.top,
- RECTWIDTH(rc),RECTHEIGHT(rc),
- SWP_NOZORDER | SWP_NOACTIVATE);
- g_ts.fSelfSizing = FALSE;
- }
- else
- ASSERT(0); // tmp unhide above
- Tray_StuckTrayChange();
- }
- if (fWinIni)
- Tray_SizeWindows();
- if (fHiding) {
- TrayShowWindow(SW_SHOWNA);
- }
- }
- //----------------------------------------------------------------------------
- TCHAR const c_szCheckAssociations[] = TEXT("CheckAssociations");
- //----------------------------------------------------------------------------
- // Returns true if GrpConv says we should check extensions again (and then
- // clears the flag).
- // The assumption here is that runonce gets run before we call this (so
- // GrpConv -s can set this).
- BOOL Tray_CheckAssociations(void)
- {
- DWORD dw = 0;
- DWORD cb = SIZEOF(dw);
- if (Reg_GetStruct(g_hkeyExplorer, NULL, c_szCheckAssociations,
- &dw, &cb) && dw)
- {
- dw = 0;
- Reg_SetStruct(g_hkeyExplorer, NULL, c_szCheckAssociations, &dw, SIZEOF(dw));
- return TRUE;
- }
- return FALSE;
- }
- ULONG _RegisterNotify(HWND hwnd, UINT nMsg, LPITEMIDLIST pidl, BOOL fRecursive );
- //----------------------------------------------------------------------------
- void Tray_RegisterDesktopNotify()
- {
- LPITEMIDLIST pidl;
- TraceMsg(TF_TRAY, "c.rdn: Notify for desktop.");
- if (!g_ts.uDesktopNotify)
- {
- pidl = SHCloneSpecialIDList(NULL, CSIDL_DESKTOPDIRECTORY, TRUE);
- if (pidl)
- {
- g_ts.uDesktopNotify = _RegisterNotify(g_ts.hwndMain, WMTRAY_DESKTOPCHANGE, pidl, FALSE);
- ILFree(pidl);
- }
- }
- if (!SHRestricted(REST_NOCOMMONGROUPS) && !g_ts.uCommonDesktopNotify)
- {
- pidl = SHCloneSpecialIDList(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, TRUE);
- if (pidl)
- {
- g_ts.uCommonDesktopNotify = _RegisterNotify(g_ts.hwndMain, WMTRAY_DESKTOPCHANGE, pidl, FALSE);
- ILFree(pidl);
- }
- }
- }
- HWND Tray_GetClockWindow(void)
- {
- return (HWND)SendMessage(g_ts.hwndNotify, TNM_GETCLOCK, 0, 0L);
- }
- UINT Tray_GetStartIDB()
- {
- UINT id;
- #ifdef WINNT
- if (IsOS(OS_TERMINALCLIENT))
- {
- id = IDB_TERMINALSERVICESBKG;
- }
- else if (IsOS(OS_WIN2000DATACENTER))
- {
- id = IDB_DCSERVERSTARTBKG;
- }
- else if (IsOS(OS_SERVERAPPLIANCE))
- {
- id = IDB_SRVAPPSTARTBKG;
- }
- else if (IsOS(OS_WIN2000ADVSERVER))
- {
- id = IDB_ADVSERVERSTARTBKG;
- }
- else if (IsOS(OS_WIN2000SERVER))
- {
- id = IDB_SERVERSTARTBKG;
- }
- else if (IsOS(OS_WIN2000EMBED))
- {
- id = IDB_EMBEDDED;
- }
- else
- {
- id = IDB_STARTBKG;
- }
- #else
- if (IsOS(OS_MEMPHIS_GOLD))
- {
- id = IDB_STARTBKG;
- }
- else
- {
- id = IDB_START95BK;
- }
- #endif
- return id;
- }
- void Tray_CreateTrayTips()
- {
- g_ts.hwndTrayTips = CreateWindow(TOOLTIPS_CLASS, NULL,
- WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL, hinstCabinet,
- NULL);
- SetWindowZorder(g_ts.hwndTrayTips, HWND_TOPMOST);
- if (g_ts.hwndTrayTips)
- {
- HWND hwndClock;
- TOOLINFO ti;
- ti.cbSize = SIZEOF(ti);
- ti.uFlags = TTF_IDISHWND;
- ti.hwnd = v_hwndTray;
- ti.uId = (UINT_PTR)g_ts.hwndStart;
- ti.lpszText = (LPTSTR)MAKEINTRESOURCE(IDS_STARTBUTTONTIP);
- ti.hinst = hinstCabinet;
- SendMessage(g_ts.hwndTrayTips, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
- if (NULL != (hwndClock = Tray_GetClockWindow()))
- {
- ti.uFlags = 0;
- ti.uId = (UINT_PTR)hwndClock;
- ti.lpszText = LPSTR_TEXTCALLBACK;
- ti.rect.left = ti.rect.top = ti.rect.bottom = ti.rect.right = 0;
- SendMessage(g_ts.hwndTrayTips, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
- }
- }
- }
- IUnknown* Tray_CreateView();
- LRESULT Tray_CreateWindows()
- {
- if (Tray_CreateStartButton())
- {
- if (Tray_CreateClockWindow())
- {
- //
- // We need to set the tray position, before creating
- // the view window, because it will call back our
- // GetWindowRect member functions.
- //
- Tray_RestoreWindowPos();
- Tray_CreateTrayTips();
- g_ts.ptbs = Tray_CreateView();
- SendMessage(g_ts.hwndNotify, TNM_HIDECLOCK, 0, g_ts.fHideClock);
- if (g_ts.ptbs)
- {
- Tray_CreateDesktopButton();
- Tray_VerifySize(FALSE);
- Tray_SizeWindows(); // size after all windows created
- return 1;
- }
- }
- }
- return -1;
- }
- LRESULT Tray_InitStartButtonEtc()
- {
- // NOTE: This bitmap is used as a flag in CTaskBar::OnPosRectChangeDB to
- // tell when we are done initializing, so we don't resize prematurely
- g_ts.hbmpStartBkg = LoadBitmap(hinstCabinet, MAKEINTRESOURCE(Tray_GetStartIDB()));
- if (g_ts.hbmpStartBkg)
- {
- UpdateWindow(v_hwndTray);
- StartMenu_Build();
- CStartDropTarget_Register();
- PrintNotify_Init(v_hwndTray);
- if (Tray_CheckAssociations())
- CheckWinIniForAssocs();
- Tray_RegisterDesktopNotify();
- SendNotifyMessage(HWND_BROADCAST,
- RegisterWindowMessage(TEXT("TaskbarCreated")), 0, 0);
- return 1;
- }
- return -1;
- }
- void Tray_AdjustMinimizedMetrics()
- {
- MINIMIZEDMETRICS mm;
- mm.cbSize = SIZEOF(mm);
- SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, SIZEOF(mm), &mm, FALSE);
- mm.iArrange |= ARW_HIDE;
- SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, SIZEOF(mm), &mm, FALSE);
- }
- LRESULT Tray_OnCreateAsync()
- {
- LRESULT lres;
- if (g_dwProfileCAP & 0x00000004)
- {
- StartCAP();
- }
- lres = Tray_InitStartButtonEtc();
- if (g_dwProfileCAP & 0x00000004)
- {
- StopCAP();
- }
- g_ts.hMainAccel = LoadAccelerators(hinstCabinet, MAKEINTRESOURCE(ACCEL_TRAY));
- Tray_RegisterGlobalHotkeys();
- HotkeyList_Restore(v_hwndTray);
- // we run the tray thread that handles Ctrl-Esc with a high priority
- // class so that it can respond even on a stressed system.
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
- return lres;
- }
- LRESULT Tray_OnCreate(HWND hwnd)
- {
- LRESULT lres;
- v_hwndTray = hwnd;
- SendMessage(v_hwndTray, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0);
- Tray_AdjustMinimizedMetrics();
- Tray_UpdateDockingFlags();
- lres = Tray_CreateWindows();
- return lres;
- }
- void Tray_DestroyShellView()
- {
- DestroyWindow(g_ts.hwndView);
- g_ts.hwndView = NULL;
- }
- BOOL CALLBACK Tray_FullScreenEnumCallback(HMONITOR hmon, HDC hdc, LPRECT prc, LPARAM dwData)
- {
- BOOL fFullScreen; // Is there a rude app on this monitor?
- LPRECT prcRude = (LPRECT)dwData;
- if (prcRude)
- {
- RECT rc, rcMon;
- GetMonitorRect(hmon, &rcMon);
- IntersectRect(&rc, &rcMon, prcRude);
- fFullScreen = EqualRect(&rc, &rcMon);
- }
- else
- {
- fFullScreen = FALSE;
- }
- if (hmon == g_ts.hmonStuck)
- {
- g_ts.fStuckRudeApp = fFullScreen;
- }
- //
- // Tell all the appbars on the same display to get out of the way too
- //
- AppBarNotifyAll(hmon, ABN_FULLSCREENAPP, NULL, fFullScreen);
- return TRUE;
- }
- void Tray_HandleFullScreenApp(HWND hwnd)
- {
- //
- // First check to see if something has actually changed
- //
- if (g_ts.hwndRude != hwnd)
- {
- g_ts.hwndRude = hwnd;
- //
- // Enumerate all the monitors, see if the app is rude on each, adjust
- // app bars and g_ts.fStuckRudeApp as necessary. (Some rude apps, such
- // as the NT Logon Screen Saver, span multiple monitors.)
- //
- {
- LPRECT prc;
- RECT rc;
- if (hwnd && GetWindowRect(hwnd, &rc))
- {
- prc = &rc;
- }
- else
- {
- prc = NULL;
- }
- EnumDisplayMonitors(NULL, NULL, Tray_FullScreenEnumCallback, (LPARAM)prc);
- }
- //
- // Now that we've set g_ts.fStuckRudeApp, update the tray's z-order position
- //
- Tray_ResetZorder();
- //
- // stop the clock so we don't eat cycles and keep tons of code paged in
- //
- ClockCtl_HandleTrayHide(g_ts.fStuckRudeApp);
- //
- // Finally, let traynot know about whether the tray is hiding
- //
- SendMessage(g_ts.hwndNotify, TNM_RUDEAPP, g_ts.fStuckRudeApp, 0);
- }
- }
- BOOL Tray_IsTopmost()
- {
- return BOOLIFY(GetWindowLong(v_hwndTray, GWL_EXSTYLE) & WS_EX_TOPMOST);
- }
- BOOL Tray_IsStartMenuVisible()
- {
- HWND hwnd;
- if (SUCCEEDED(IUnknown_GetWindow((IUnknown*)g_ts._pmpStartMenu, &hwnd)))
- {
- return IsWindowVisible(hwnd);
- }
- return FALSE;
- }
- BOOL Tray_IsActive()
- {
- //
- // We say the tray is "active" iff:
- //
- // (a) the foreground window is the tray or a window owned by the tray, or
- // (b) the start menu is showing
- //
- BOOL fActive = FALSE;
- HWND hwnd = GetForegroundWindow();
- if (hwnd != NULL &&
- (hwnd == v_hwndTray || (GetWindowOwner(hwnd) == v_hwndTray)))
- {
- fActive = TRUE;
- }
- else if (Tray_IsStartMenuVisible())
- {
- fActive = TRUE;
- }
- return fActive;
- }
- void Tray_ResetZorder()
- {
- HWND hwndZorder, hwndZorderCurrent;
- if (g_fDesktopRaised || (g_ts.fAlwaysOnTop && !g_ts.fStuckRudeApp))
- {
- hwndZorder = HWND_TOPMOST;
- }
- else if (Tray_IsActive())
- {
- hwndZorder = HWND_TOP;
- }
- else if (g_ts.fStuckRudeApp)
- {
- hwndZorder = HWND_BOTTOM;
- }
- else
- {
- hwndZorder = HWND_NOTOPMOST;
- }
- //
- // We don't have to worry about the HWND_BOTTOM current case -- it's ok
- // to keep moving ourselves down to the bottom when there's a rude app.
- //
- // Nor do we have to worry about the HWND_TOP current case -- it's ok
- // to keep moving ourselves up to the top when we're active.
- //
- hwndZorderCurrent = Tray_IsTopmost() ? HWND_TOPMOST : HWND_NOTOPMOST;
- if (hwndZorder != hwndZorderCurrent)
- {
- // only do this if somehting has changed.
- // this keeps us from popping up over menus as desktop async
- // notifies us of it's state
- SHForceWindowZorder(v_hwndTray, hwndZorder);
- }
- }
- DWORD CALLBACK Tray_SyncThreadProc(void *hInst);
- DWORD CALLBACK Tray_MainThreadProc(void *hInst);
- void Tray_MessageLoop()
- {
- for (;;)
- {
- MSG msg;
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- if (msg.message == WM_QUIT)
- {
- if (v_hwndTray && IsWindow(v_hwndTray))
- {
- // Tell the tray to save everything off if we got here
- // without it being destroyed.
- SendMessage(v_hwndTray, WM_ENDSESSION, 1, 0);
- }
- return; // break all the way out of the main loop
- }
- if (g_ts._pmbStartMenu &&
- g_ts._pmbStartMenu->lpVtbl->IsMenuMessage(g_ts._pmbStartMenu, &msg) == S_OK)
- {
- continue;
- }
- if (g_ts.hMainAccel && TranslateAccelerator(g_ts.hwndMain, g_ts.hMainAccel, &msg))
- {
- continue;
- }
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else
- {
- WaitMessage();
- }
- }
- }
- BOOL InitTray(HINSTANCE hInst )
- {
- // put the tray on a separate thread
- return SHCreateThread(Tray_MainThreadProc, hInst, 0, Tray_SyncThreadProc);
- }
- void Tray_InitBandsite()
- {
- ASSERT(v_hwndTray);
- // we initilize the contents after all the infrastructure is created and sized properly
- // need to notify which side we're on.
- // nt5:211881: set mode *before* load, o.w. Update->RBAutoSize screwed up
- BandSite_SetMode(g_ts.ptbs, STUCK_HORIZONTAL(g_ts.uStuckPlace) ? 0 : DBIF_VIEWMODE_VERTICAL);
- BandSite_Load();
- // now that the mode is set, we need to force an update because we
- // explicitly avoided the update during BandSite_Load
- BandSite_Update(g_ts.ptbs);
- BandSite_UIActivateDBC(g_ts.ptbs, DBC_SHOW);
- }
- void Tray_KickStartAutohide()
- {
- if (g_ts.uAutoHide & AH_ON)
- {
- // tray always starts out hidden on autohide
- g_ts.uAutoHide = AH_ON | AH_HIDING;
- // we and many apps rely upon us having calculated the size correctly
- Tray_Unhide();
- // register it
- if (!IAppBarSetAutoHideBar(v_hwndTray, TRUE, g_ts.uStuckPlace))
- {
- // don't bother putting up UI in this case
- // if someone is there just silently convert to normal
- // (the shell is booting who would be there anyway?)
- Tray_SetAutoHideState(FALSE);
- }
- }
- }
- void Tray_InitNonzeroGlobals()
- {
- // initalize globals that need to be non-zero
- g_ts.wThreadCmd = SMCT_DONE;
- g_ts.hBIOS = INVALID_HANDLE_VALUE;
- if (GetSystemMetrics(SM_SLOWMACHINE))
- {
- g_dtSlideHide = 0; // dont slide the tray out
- g_dtSlideShow = 0;
- }
- else
- {
- //BUGBUG: we should read from registry.
- g_dtSlideHide = 400;
- g_dtSlideShow = 200;
- }
- }
- void Tray_CreateTrayWindow(HINSTANCE hinst)
- {
- DWORD dwExStyle = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW;
- dwExStyle |= IS_BIDI_LOCALIZED_SYSTEM() ? dwExStyleRTLMirrorWnd : 0L;
- v_hwndTray = CreateWindowEx(dwExStyle,
- TEXT(WNDCLASS_TRAYNOTIFY), NULL,
- WS_CLIPCHILDREN | WS_POPUP | WS_BORDER | WS_THICKFRAME,
- 0, 0, 0, 0, NULL, NULL, hinst, NULL);
- }
- DWORD CALLBACK Tray_SyncThreadProc(void *pv)
- {
- MSG msg;
- if (g_dwProfileCAP & 0x00000002)
- {
- StartCAP();
- }
- // make sure the message queue has been created...
- PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE );
- OleInitialize( NULL );
- Tray_InitNonzeroGlobals();
- Tray_CreateTrayWindow((HINSTANCE)pv);
- if (!v_hwndTray || !g_ts.ptbs)
- {
- OleUninitialize();
- return FALSE;
- }
- //
- // obey the "always on top" flag
- //
- Tray_ResetZorder();
- Tray_KickStartAutohide();
- Tray_InitBandsite();
- //
- // make sure we clip the taskbar to the current monitor before showing it
- //
- Tray_ClipWindow(TRUE);
- //
- // it looks really dorky for the tray to pop up and rehide at logon
- // if we are autohide don't activate the tray when we show it
- // if we aren't autohide do what Win95 did (tray is active by default)
- //
- ShowWindow(v_hwndTray,
- ((g_ts.uAutoHide & AH_HIDING)? SW_SHOWNA : SW_SHOW));
- UpdateWindow(v_hwndTray);
- Tray_StuckTrayChange();
- SetTimer(v_hwndTray, IDT_HANDLEDELAYBOOTSTUFF, 10 * 1000, NULL);
- if (g_dwProfileCAP & 0x00020000)
- {
- StopCAP();
- }
- return FALSE;
- }
- // the rest of the thread proc that includes the message loop
- DWORD CALLBACK Tray_MainThreadProc(void *pv)
- {
- if (!v_hwndTray)
- return FALSE;
- Tray_OnCreateAsync();
- Tray_MessageLoop();
- OleUninitialize();
- return FALSE;
- }
- #define DM_IANELHK 0
- //---------------------------------------------------------------------------
- ULONG _RegisterNotify(HWND hwnd, UINT nMsg, LPITEMIDLIST pidl, BOOL fRecursive)
- {
- SHChangeNotifyEntry fsne;
- ULONG lReturn;
- fsne.fRecursive = fRecursive;
- fsne.pidl = pidl;
- //
- // Don't watch for attribute changes since we just want the
- // name and icon. For example, if a printer is paused, we don't
- // want to re-enumerate everything.
- //
- lReturn = SHChangeNotifyRegister(hwnd, SHCNRF_NewDelivery | SHCNRF_ShellLevel | SHCNRF_InterruptLevel,
- ((SHCNE_DISKEVENTS | SHCNE_UPDATEIMAGE) & ~SHCNE_ATTRIBUTES), nMsg, 1, &fsne);
- return lReturn;
- }
- //---------------------------------------------------------------------------
- ULONG RegisterNotify(HWND hwnd, UINT nMsg, LPITEMIDLIST pidl)
- {
- return _RegisterNotify(hwnd, nMsg, pidl, TRUE);
- }
- //---------------------------------------------------------------------------
- void UnregisterNotify(ULONG nNotify)
- {
- if (nNotify)
- SHChangeNotifyDeregister(nNotify);
- }
- //----------------------------------------------------------------------------
- #define HKIF_NULL 0
- #define HKIF_CACHED 1
- #define HKIF_FREEPIDLS 2
- typedef struct
- {
- LPITEMIDLIST pidlFolder;
- LPITEMIDLIST pidlItem;
- WORD wGHotkey;
- // BOOL fCached;
- WORD wFlags;
- } HOTKEYITEM, *PHOTKEYITEM;
- const TCHAR c_szSlashCLSID[] = TEXT("\CLSID");
- //
- // like OLE GetClassFile(), but it only works on ProgIDCLSID type registration
- // not real doc files or pattern matched files
- //
- HRESULT _CLSIDFromExtension(LPCTSTR pszExt, CLSID *pclsid)
- {
- TCHAR szProgID[80];
- ULONG cb = SIZEOF(szProgID);
- if (RegQueryValue(HKEY_CLASSES_ROOT, pszExt, szProgID, &cb) == ERROR_SUCCESS)
- {
- TCHAR szCLSID[80];
- lstrcat(szProgID, c_szSlashCLSID);
- cb = SIZEOF(szCLSID);
- if (RegQueryValue(HKEY_CLASSES_ROOT, szProgID, szCLSID, &cb) == ERROR_SUCCESS)
- return SHCLSIDFromString(szCLSID, pclsid);
- }
- return E_FAIL;
- }
- //----------------------------------------------------------------------------
- // this gets hotkeys for files given a folder and a pidls it is much faster
- // than _GetHotkeyFromPidls since it does not need to bind to an IShellFolder
- // to interrogate it. if you have access to the item's IShellFolder, call this
- // one, especially in a loop.
- //
- WORD _GetHotkeyFromFolderItem(LPSHELLFOLDER psf, LPCITEMIDLIST pidl)
- {
- // TCHAR szPath[MAX_PATH];
- WORD wHotkey = 0;
- DWORD dwAttrs = SFGAO_LINK;
- //
- // Make sure it is an SFGAO_LINK so we don't load a big handler dll
- // just to get back E_NOINTERFACE...
- //
- if (SUCCEEDED(psf->lpVtbl->GetAttributesOf(psf, 1, &pidl, &dwAttrs)) &&
- (dwAttrs & SFGAO_LINK))
- {
- IShellLink * pLink;
- UINT rgfInOut = 0;
- if ( SUCCEEDED( psf->lpVtbl->GetUIObjectOf(psf, NULL, 1, &pidl, &IID_IShellLink, &rgfInOut, &pLink )))
- {
- pLink->lpVtbl->GetHotkey(pLink, &wHotkey);
- pLink->lpVtbl->Release(pLink);
- }
- }
- return wHotkey;
- }
- //----------------------------------------------------------------------------
- UINT HotkeyList_GetFreeItemIndex(void)
- {
- int i, cItems;
- PHOTKEYITEM phki;
- ASSERT(IS_VALID_HANDLE(g_ts.hdsaHKI, DSA));
- cItems = DSA_GetItemCount(g_ts.hdsaHKI);
- for (i=0; i<cItems; i++)
- {
- phki = DSA_GetItemPtr(g_ts.hdsaHKI, i);
- if (!phki->wGHotkey)
- {
- ASSERT(!phki->pidlFolder);
- ASSERT(!phki->pidlItem);
- break;
- }
- }
- return i;
- }
- //----------------------------------------------------------------------------
- // Weird, Global hotkeys use different flags for modifiers than window hotkeys
- // (and hotkeys returned by the hotkey control)
- WORD MapHotkeyToGlobalHotkey(WORD wHotkey)
- {
- UINT nVirtKey;
- UINT nMod = 0;
- // Map the modifiers.
- if (HIBYTE(wHotkey) & HOTKEYF_SHIFT)
- nMod |= MOD_SHIFT;
- if (HIBYTE(wHotkey) & HOTKEYF_CONTROL)
- nMod |= MOD_CONTROL;
- if (HIBYTE(wHotkey) & HOTKEYF_ALT)
- nMod |= MOD_ALT;
- nVirtKey = LOBYTE(wHotkey);
- return (WORD)((nMod*256) + nVirtKey);
- }
- //----------------------------------------------------------------------------
- // NB This takes a regular window hotkey not a global hotkey (it does
- // the convertion for you).
- int HotkeyList_Add(WORD wHotkey, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlItem, BOOL fClone)
- {
- LPCITEMIDLIST pidl1, pidl2;
- if (wHotkey)
- {
- HOTKEYITEM hki;
- int i = HotkeyList_GetFreeItemIndex();
- ASSERT(IS_VALID_HANDLE(g_ts.hdsaHKI, DSA));
- // DebugMsg(DM_IANELHK, "c.hl_a: Hotkey %x with id %d.", wHotkey, i);
- if (fClone)
- {
- pidl1 = ILClone(pidlFolder);
- pidl2 = ILClone(pidlItem);
- hki.wFlags = HKIF_FREEPIDLS;
- }
- else
- {
- pidl1 = pidlFolder;
- pidl2 = pidlItem;
- hki.wFlags = HKIF_NULL;
- }
- hki.pidlFolder = (LPITEMIDLIST)pidl1;
- hki.pidlItem = (LPITEMIDLIST)pidl2;
- hki.wGHotkey = MapHotkeyToGlobalHotkey(wHotkey);
- DSA_SetItem(g_ts.hdsaHKI, i, &hki);
- return i;
- }
- return -1;
- }
- //----------------------------------------------------------------------------
- // NB Cached hotkeys have their own pidls that need to be free but
- // regular hotkeys just keep a pointer to pidls used by the startmenu and
- // so don't.
- int HotkeyList_AddCached(WORD wGHotkey, LPITEMIDLIST pidl)
- {
- int i = -1;
- if (wGHotkey)
- {
- LPITEMIDLIST pidlItem = ILClone(ILFindLastID(pidl));
- ASSERT(IS_VALID_HANDLE(g_ts.hdsaHKI, DSA));
- if (pidlItem)
- {
- if (ILRemoveLastID(pidl))
- {
- HOTKEYITEM hki;
- i = HotkeyList_GetFreeItemIndex();
- // DebugMsg(DM_IANELHK, "c.hl_ac: Hotkey %x with id %d.", wGHotkey, i);
- hki.pidlFolder = pidl;
- hki.pidlItem = pidlItem;
- hki.wGHotkey = wGHotkey;
- hki.wFlags = HKIF_CACHED | HKIF_FREEPIDLS;
- DSA_SetItem(g_ts.hdsaHKI, i, &hki);
- }
- }
- }
- return i;
- }
- const TCHAR c_szHotkeys[] = TEXT("Hotkeys");
- //----------------------------------------------------------------------------
- // NB Must do this before destroying the startmenu since the hotkey list
- // uses it's pidls in a lot of cases.
- int HotkeyList_Save(void)
- {
- int cCached = 0;
- TraceMsg(TF_TRAY, "HotkeyList_Save: Saving global hotkeys.");
- if (EVAL(g_ts.hdsaHKI))
- {
- int i, cItems;
- PHOTKEYITEM phki;
- LPITEMIDLIST pidl;
- int cbData = 0;
- TCHAR szValue[32];
- LPBYTE pData;
- ASSERT(IS_VALID_HANDLE(g_ts.hdsaHKI, DSA));
- cItems = DSA_GetItemCount(g_ts.hdsaHKI);
- for (i=0; i<cItems; i++)
- {
- phki = DSA_GetItemPtr(g_ts.hdsaHKI, i);
- // Non cached item?
- if (phki->wGHotkey && !(phki->wFlags & HKIF_CACHED))
- {
- // Yep, save it.
- pidl = ILCombine(phki->pidlFolder, phki->pidlItem);
- if (pidl)
- {
- cbData = SIZEOF(WORD) + ILGetSize(pidl);
- pData = LocalAlloc(GPTR, cbData);
- if (pData)
- {
- // DebugMsg(DM_TRACE, "c.hl_s: Saving %x.", phki->wGHotkey );
- *((LPWORD)pData) = phki->wGHotkey;
- memcpy(pData+SIZEOF(WORD), pidl, cbData-SIZEOF(DWORD));
- wsprintf(szValue, TEXT("%d"), cCached);
- Reg_SetStruct(g_hkeyExplorer, c_szHotkeys, szValue, pData , cbData);
- cCached++;
- LocalFree(pData);
- }
- ILFree(pidl);
- }
- }
- }
- }
- return cCached;
- }
- //----------------------------------------------------------------------------
- HKEY Reg_EnumValueCreate(HKEY hkey, LPCTSTR pszSubkey)
- {
- HKEY hkeyOut;
- if (RegOpenKeyEx(hkey, pszSubkey, 0L, KEY_ALL_ACCESS, &hkeyOut) == ERROR_SUCCESS)
- {
- return hkeyOut;
- }
- return(NULL);
- }
- //----------------------------------------------------------------------------
- int Reg_EnumValue(HKEY hkey, int i, LPBYTE pData, int cbData)
- {
- TCHAR szValue[MAX_PATH];
- DWORD cchValue;
- DWORD dw;
- DWORD dwType;
- cchValue = ARRAYSIZE(szValue);
- if (RegEnumValue(hkey, i, szValue, &cchValue, &dw, &dwType, pData,
- &cbData) == ERROR_SUCCESS)
- {
- return cbData;
- }
- return 0;
- }
- //----------------------------------------------------------------------------
- BOOL Reg_EnumValueDestroy(HKEY hkey)
- {
- return RegCloseKey(hkey) == ERROR_SUCCESS;
- }
- //----------------------------------------------------------------------------
- int HotkeyList_Restore(HWND hwnd)
- {
- int i = 0;
- HKEY hkey;
- LPBYTE pData;
- int cbData;
- WORD wGHotkey;
- int id;
- LPITEMIDLIST pidl;
- // If shdocvw fails to load for some reason, we will GP-fault if we
- // don't validate hdsaHKI.
- if (EVAL(g_ts.hdsaHKI))
- {
- TraceMsg(TF_TRAY, "HotkeyList_Restore: Restoring global hotkeys...");
- hkey = Reg_EnumValueCreate(g_hkeyExplorer, c_szHotkeys);
- if (hkey)
- {
- cbData = Reg_EnumValue(hkey, i, NULL, 0);
- while (cbData)
- {
- pData = LocalAlloc(GPTR, cbData);
- if (pData)
- {
- Reg_EnumValue(hkey, i, pData, cbData);
- // Get the hotkey and the pidl components.
- wGHotkey = *((LPWORD)pData);
- pidl = ILClone((LPITEMIDLIST)(pData+SIZEOF(WORD)));
- // DebugMsg(DM_TRACE, "c.hl_r: Restoring %x", wGHotkey);
- id = HotkeyList_AddCached(wGHotkey, pidl);
- if (id != -1)
- Tray_RegisterHotkey(hwnd, id);
- LocalFree(pData);
- }
- i++;
- cbData = Reg_EnumValue(hkey, i, NULL, 0);
- }
- Reg_EnumValueDestroy(hkey);
- // Nuke the cached stuff.
- RegDeleteKey(g_hkeyExplorer, c_szHotkeys);
- }
- }
- return i;
- }
- //----------------------------------------------------------------------------
- // NB Again, this takes window hotkey not a Global one.
- // NB This doesn't delete cached hotkeys.
- int HotkeyList_Remove(WORD wHotkey)
- {
- if (EVAL(g_ts.hdsaHKI))
- {
- int i, cItems;
- PHOTKEYITEM phki;
- WORD wGHotkey;
- ASSERT(IS_VALID_HANDLE(g_ts.hdsaHKI, DSA));
- // DebugMsg(DM_IANELHK, "c.hl_r: Remove hotkey for %x" , wHotkey);
- // Unmap the modifiers.
- wGHotkey = MapHotkeyToGlobalHotkey(wHotkey);
- cItems = DSA_GetItemCount(g_ts.hdsaHKI);
- for (i=0; i<cItems; i++)
- {
- phki = DSA_GetItemPtr(g_ts.hdsaHKI, i);
- if (phki && !(phki->wFlags & HKIF_CACHED) && (phki->wGHotkey == wGHotkey))
- {
- // DebugMsg(DM_IANELHK, "c.hl_r: Invalidating %d", i);
- if (phki->wFlags & HKIF_FREEPIDLS)
- {
- if (phki->pidlFolder)
- ILFree(phki->pidlFolder);
- if (phki->pidlItem)
- ILFree(phki->pidlItem);
- }
- phki->wGHotkey = 0;
- phki->pidlFolder = NULL;
- phki->pidlItem = NULL;
- phki->wFlags &= ~HKIF_FREEPIDLS;
- return i;
- }
- }
- }
- return -1;
- }
- //----------------------------------------------------------------------------
- // NB This takes a global hotkey.
- int HotkeyList_RemoveCached(WORD wGHotkey)
- {
- int i, cItems;
- PHOTKEYITEM phki;
- ASSERT(IS_VALID_HANDLE(g_ts.hdsaHKI, DSA));
- // DebugMsg(DM_IANELHK, "c.hl_rc: Remove hotkey for %x" , wGHotkey);
- cItems = DSA_GetItemCount(g_ts.hdsaHKI);
- for (i=0; i<cItems; i++)
- {
- phki = DSA_GetItemPtr(g_ts.hdsaHKI, i);
- if (phki && (phki->wFlags & HKIF_CACHED) && (phki->wGHotkey == wGHotkey))
- {
- // DebugMsg(DM_IANELHK, "c.hl_r: Invalidating %d", i);
- if (phki->wFlags & HKIF_FREEPIDLS)
- {
- if (phki->pidlFolder)
- ILFree(phki->pidlFolder);
- if (phki->pidlItem)
- ILFree(phki->pidlItem);
- }
- phki->pidlFolder = NULL;
- phki->pidlItem = NULL;
- phki->wGHotkey = 0;
- phki->wFlags &= ~(HKIF_CACHED | HKIF_FREEPIDLS);
- return i;
- }
- }
- return -1;
- }
- //----------------------------------------------------------------------------
- // NB Some (the ones not marked HKIF_FREEPIDLS) of the items in the list of hotkeys
- // have pointers to idlists used by the filemenu so they are only valid for
- // the lifetime of the filemenu.
- BOOL HotkeyList_Create(void)
- {
- if (!g_ts.hdsaHKI)
- {
- // DebugMsg(DM_TRACE, "c.hkl_c: Creating global hotkey list.");
- g_ts.hdsaHKI = DSA_Create(SIZEOF(HOTKEYITEM), 0);
- }
- if (g_ts.hdsaHKI)
- return TRUE;
- return FALSE;
- }
- void StartMenu_AddTask(IShellTaskScheduler* pSystemScheduler, int nFolder, int iPriority)
- {
- LPITEMIDLIST pidlFolder;
- IShellHotKey * pshk;
- if (FAILED(CHotKey_Create(&pshk)))
- return;
- SHGetSpecialFolderLocation(NULL, nFolder, &pidlFolder);
- if (pidlFolder)
- {
- LPITEMIDLIST pidlParent = ILClone(pidlFolder);
- if (pidlParent)
- {
- IShellFolder* psf;
- ILRemoveLastID(pidlParent);
- psf = BindToFolder(pidlParent);
- if (psf)
- {
- HRESULT hres;
- IStartMenuTask * psmt;
- BOOL bDesktop = (CSIDL_DESKTOPDIRECTORY == nFolder || CSIDL_COMMON_DESKTOPDIRECTORY == nFolder);
- hres = CoCreateInstance(bDesktop ? &CLSID_DesktopTask : &CLSID_StartMenuTask,
- NULL, CLSCTX_INPROC, &IID_IStartMenuTask, (void **) &psmt);
- if (SUCCEEDED(hres))
- {
- DWORD dwFlags = bDesktop ? 0 : ITSFT_RECURSE;
- LONG nMaxRecursion = bDesktop ? 32 : 2 ;
- // Initialize the task. Set task priority according to max
- // folder depth. We'll assume 32 is a reasonable number.
- hres = psmt->lpVtbl->InitTaskSFT(psmt, psf, pidlFolder, nMaxRecursion, dwFlags, 32);
- if (SUCCEEDED(hres))
- {
- IRunnableTask * ptask;
- psmt->lpVtbl->InitTaskSMT(psmt, pshk, iPriority);
- hres = psmt->lpVtbl->QueryInterface(psmt, &IID_IRunnableTask, (void **)&ptask);
- if (SUCCEEDED(hres))
- {
- // Add it to the scheduler
- hres = pSystemScheduler->lpVtbl->AddTask(pSystemScheduler, ptask,
- &CLSID_StartMenuTask,
- 0, 32);
- ptask->lpVtbl->Release(ptask);
- }
- }
- psmt->lpVtbl->Release(psmt);
- }
- if (FAILED(hres))
- TraceMsg(TF_ERROR, "StartMenu_AddTask: failed to create start menu task");
- psf->lpVtbl->Release(psf);
- }
- ILFree(pidlParent);
- }
- ILFree(pidlFolder);
- }
- pshk->lpVtbl->Release(pshk);
- }
- //----------------------------------------------------------------------------
- void StartMenu_Build()
- {
- HRESULT hres;
- ATOMICRELEASET(g_ts._pmpStartMenu, IMenuPopup);
- ATOMICRELEASET(g_ts._pmbStartMenu, IMenuBand);
- g_uStartButtonAllowPopup = RegisterWindowMessage(TEXT("StartButtonAllowPopup"));
- hres = StartMenuHost_Create(&g_ts._pmpStartMenu, &g_ts._pmbStartMenu);
- if (SUCCEEDED(hres))
- {
- IBanneredBar* pbb;
- hres = g_ts._pmpStartMenu->lpVtbl->QueryInterface(g_ts._pmpStartMenu,
- &IID_IBanneredBar, (void**)&pbb);
- if (SUCCEEDED(hres))
- {
- pbb->lpVtbl->SetBitmap(pbb, g_ts.hbmpStartBkg);
- if (g_ts.fSMSmallIcons)
- pbb->lpVtbl->SetIconSize(pbb, BMICON_SMALL);
- else
- pbb->lpVtbl->SetIconSize(pbb, BMICON_LARGE);
- pbb->lpVtbl->Release(pbb);
- }
- HotkeyList_Create();
- }
- else
- TraceMsg(TF_ERROR, "Could not create StartMenu");
- }
- //----------------------------------------------------------------------------
- void StartMenu_Destroy()
- {
- IUnknown_SetSite((IUnknown*)g_ts._pmpStartMenu, NULL);
- ATOMICRELEASET(g_ts._pmpStartMenu, IMenuPopup);
- ATOMICRELEASET(g_ts._pmbStartMenu, IMenuBand);
- }
- //----------------------------------------------------------------------------
- void _ForceStartButtonUp()
- {
- MSG msg;
- // don't do that check message pos because it gets screwy with
- // keyboard cancel. and besides, we always want it cleared after
- // track menu popup is done.
- // do it twice to be sure it's up due to the uDown cycling twice in
- // the subclassing stuff
- // pull off any button downs
- PeekMessage(&msg, g_ts.hwndStart, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
- SendMessage(g_ts.hwndStart, BM_SETSTATE, FALSE, 0);
- SendMessage(g_ts.hwndStart, BM_SETSTATE, FALSE, 0);
- // The user cancelled the Start menu, so a new press of the Windows key
- // should be considered "Reopen the Start Menu" instead of "Cancel the
- // Start Menu and return to the previous window."
- g_hwndPrevFocus = NULL;
- }
- int Tray_TrackMenu(HMENU hmenu)
- {
- TPMPARAMS tpm;
- int iret;
- tpm.cbSize = SIZEOF(tpm);
- GetClientRect(g_ts.hwndStart, &tpm.rcExclude);
- MapWindowPoints(g_ts.hwndStart, NULL, (LPPOINT)&tpm.rcExclude, 2);
- SendMessage(g_ts.hwndTrayTips, TTM_ACTIVATE, FALSE, 0L);
- iret = TrackPopupMenuEx(hmenu, TPM_VERTICAL | TPM_BOTTOMALIGN | TPM_RETURNCMD,
- tpm.rcExclude.left, tpm.rcExclude.bottom, v_hwndTray, &tpm);
- SendMessage(g_ts.hwndTrayTips, TTM_ACTIVATE, TRUE, 0L);
- return iret;
- }
- //----------------------------------------------------------------------------
- // Keep track of the menu font name and weight so we can redo the startmenu if
- // these change before getting notified via win.ini.
- BOOL StartMenu_FontChange(void)
- {
- NONCLIENTMETRICS ncm;
- static TCHAR lfFaceName[LF_FACESIZE] = TEXT("");
- static long lfHeight = 0;
- ncm.cbSize = SIZEOF(ncm);
- if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, SIZEOF(ncm), &ncm, FALSE ))
- {
- if (!*lfFaceName)
- {
- // DebugMsg(DM_TRACE, "sm_fc: No menu font - initing.");
- lstrcpy(lfFaceName, ncm.lfMenuFont.lfFaceName);
- lfHeight = ncm.lfMenuFont.lfHeight;
- return FALSE;
- }
- else if ((lstrcmpi(ncm.lfMenuFont.lfFaceName, lfFaceName) == 0) &&
- (ncm.lfMenuFont.lfHeight == lfHeight))
- {
- // DebugMsg(DM_TRACE, "sm_fc: Menu font unchanged.");
- return FALSE;
- }
- else
- {
- // DebugMsg(DM_TRACE, "sm_fc: Menu font changed.");
- lstrcpy(lfFaceName, ncm.lfMenuFont.lfFaceName);
- lfHeight = ncm.lfMenuFont.lfHeight;
- return TRUE;
- }
- }
- return FALSE;
- }
- /*------------------------------------------------------------------
- ** Respond to a button's pressing by bringing up the appropriate menu.
- ** Clean up the button depression when the menu is dismissed.
- **------------------------------------------------------------------*/
- void ToolbarMenu()
- {
- RECTL rcExclude;
- POINTL ptPop;
- DWORD dwFlags = MPPF_KEYBOARD; // Assume that we're popuping
- // up because of the keyboard
- // This is for the underlines on NT5
- if (g_ts.hwndStartBalloon)
- {
- DontShowTheStartButtonBalloonAnyMore();
- ShowWindow(g_ts.hwndStartBalloon, SW_HIDE);
- DestroyStartButtonBalloon();
- }
- SetActiveWindow(v_hwndTray);
- g_ts.bMainMenuInit = TRUE;
- GetClientRect(g_ts.hwndStart, (RECT *)&rcExclude);
- MapWindowRect(g_ts.hwndStart, HWND_DESKTOP, &rcExclude);
- ptPop.x = rcExclude.left;
- ptPop.y = rcExclude.top;
- // Close any Context Menus
- SendMessage(v_hwndTray, WM_CANCELMODE, 0, 0);
- // Is the "Activate" button down (If the buttons are swapped, then it's the
- // right button, otherwise the left button)
- if (GetKeyState(GetSystemMetrics(SM_SWAPBUTTON)?VK_RBUTTON:VK_LBUTTON) < 0)
- {
- dwFlags = 0; // Then set to the default
- }
- else
- {
- // Since the user has launched the start button by Ctrl-Esc, or some other worldly
- // means, then turn the rect on.
- SendMessage(g_ts.hwndStart, WM_UPDATEUISTATE, MAKEWPARAM(UIS_CLEAR,
- UISF_HIDEFOCUS), 0);
- }
- if (g_ts._pmpStartMenu) {
- g_ts._pmpStartMenu->lpVtbl->Popup(g_ts._pmpStartMenu, &ptPop, &rcExclude, dwFlags);
- TraceMsg(DM_MISC, "e.tbm: dwFlags=%x (0=mouse 1=key)", dwFlags);
- UEMFireEvent(&UEMIID_SHELL, UEME_INSTRBROWSER, UEMF_INSTRUMENT, UIBW_UIINPUT, dwFlags ? UIBL_INPMENU : UIBL_INPMOUSE);
- }
- }
- //
- // can't use SubtractRect sometimes because of inclusion limitations
- //
- void AppBarSubtractRect(PAPPBAR pab, LPRECT lprc)
- {
- switch (pab->uEdge) {
- case ABE_TOP:
- if (pab->rc.bottom > lprc->top)
- lprc->top = pab->rc.bottom;
- break;
- case ABE_LEFT:
- if (pab->rc.right > lprc->left)
- lprc->left = pab->rc.right;
- break;
- case ABE_BOTTOM:
- if (pab->rc.top < lprc->bottom)
- lprc->bottom = pab->rc.top;
- break;
- case ABE_RIGHT:
- if (pab->rc.left < lprc->right)
- lprc->right = pab->rc.left;
- break;
- }
- }
- void AppBarSubtractRects(HMONITOR hmon, LPRECT lprc)
- {
- int i;
- if (!g_ts.hdpaAppBars)
- return;
- i = DPA_GetPtrCount(g_ts.hdpaAppBars);
- while (i--)
- {
- PAPPBAR pab = (PAPPBAR)DPA_GetPtr(g_ts.hdpaAppBars, i);
- //
- // autohide bars are not in our DPA or live on the edge
- // BUGBUG: don't subtract the appbar if it is not always on top????
- // don't subtract the appbar if it's on a different display
- //
- if (hmon == MonitorFromRect(&pab->rc, MONITOR_DEFAULTTONULL))
- AppBarSubtractRect(pab, lprc);
- }
- }
- #define RWA_NOCHANGE 0
- #define RWA_CHANGED 1
- #define RWA_BOTTOMMOSTTRAY 2
- // BUGBUG: (dli) This is a hack put in because bottommost tray is wierd, once
- // it becomes a toolbar, this code should go away.
- // In the bottommost tray case, even though the work area has not changed,
- // we should notify the desktop.
- int RecomputeWorkArea(HWND hwndCause, HMONITOR hmon, LPRECT prcWork)
- {
- int iRet = RWA_NOCHANGE;
- MONITORINFO mi;
- //
- // tell everybody that this window changed positions _on_this_monitor_
- // note that this notify happens even if we don't change the work area
- // since it may cause another app to change the work area...
- //
- PostMessage(v_hwndTray, TM_RELAYPOSCHANGED, (WPARAM)hwndCause,
- (LPARAM)hmon);
- //
- // get the current info for this monitor
- // we subtract down from the display rectangle to build the work area
- //
- mi.cbSize = sizeof(mi);
- if (GetMonitorInfo(hmon, &mi))
- {
- //
- // don't subtract the tray if it is autohide
- // don't subtract the tray if it is not always on top
- // don't subtract the tray if it's on a different display
- //
- if (!(g_ts.uAutoHide & AH_ON) && g_ts.fAlwaysOnTop &&
- (hmon == g_ts.hmonStuck))
- {
- SubtractRect(prcWork, &mi.rcMonitor,
- &g_ts.arStuckRects[g_ts.uStuckPlace]);
- }
- else
- *prcWork = mi.rcMonitor;
- //
- // now subtract off all the appbars on this display
- //
- AppBarSubtractRects(hmon, prcWork);
- //
- // return whether we changed anything
- //
- if (!EqualRect(prcWork, &mi.rcWork))
- iRet = RWA_CHANGED;
- else if (!(g_ts.uAutoHide & AH_ON) && (!g_ts.fAlwaysOnTop) &&
- (!IsRectEmpty(&g_ts.arStuckRects[g_ts.uStuckPlace])))
- // NOTE: This is the bottommost case, it only applies for the tray.
- // this should be taken out when bottommost tray becomes toolbar
- iRet = RWA_BOTTOMMOSTTRAY;
- }
- else
- {
- // NOTE: This should never happen, if it does because of USER problem,
- // we just say NO CHANGE!!!!
- ASSERTMSG(FALSE, "GetMonitorInfo should never fail! We should have updated our hmonOld or hmonStuck on time");
- iRet = RWA_NOCHANGE;
- }
- return iRet;
- }
- //
- // Nashville's debug USER draws silly "Monitor N CXxCYxBPP" crud on the display
- //
- #if !defined(WINNT) && defined(DEBUG)
- #define FORCE_INVALIDATE_WORKAREA TRUE
- #else
- #define FORCE_INVALIDATE_WORKAREA FALSE
- #endif
- void RedrawDesktop(LPRECT prcWork)
- {
- // This rect point should always be valid (dli)
- RIP(prcWork);
- if (v_hwndDesktop && (FORCE_INVALIDATE_WORKAREA || g_fCleanBoot))
- {
- MapWindowPoints(NULL, v_hwndDesktop, (LPPOINT)prcWork, 2);
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.sac invalidating desktop rect {%d,%d,%d,%d}"), prcWork->left, prcWork->top, prcWork->right, prcWork->bottom);
- RedrawWindow(v_hwndDesktop, prcWork, NULL,
- RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
- }
- }
- void StuckAppChange(HWND hwndCause, LPCRECT prcOld, LPCRECT prcNew, BOOL bTray)
- {
- RECT rcWork1, rcWork2;
- HMONITOR hmon1, hmon2 = 0;
- int iChange = 0;
- //
- // BUGBUG:
- // there are cases where we end up setting the work area multiple times
- // we need to keep a static array of displays that have changed and a
- // reenter count so we can avoid pain of sending notifies to the whole
- // planet...
- //
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.sac from AppBar %08X"), hwndCause);
- //
- // see if the work area changed on the display containing prcOld
- //
- if (prcOld)
- {
- if (bTray)
- hmon1 = g_ts.hmonOld;
- else
- hmon1 = MonitorFromRect(prcOld, MONITOR_DEFAULTTONEAREST);
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.sac old pos {%d,%d,%d,%d} on monitor %08X"), prcOld->left, prcOld->top, prcOld->right, prcOld->bottom, hmon1);
- if (hmon1)
- {
- int iret = RecomputeWorkArea(hwndCause, hmon1, &rcWork1);
- if (iret == RWA_CHANGED)
- iChange = 1;
- if (iret == RWA_BOTTOMMOSTTRAY)
- iChange = 4;
- }
- }
- else
- hmon1 = NULL;
- //
- // see if the work area changed on the display containing prcNew
- //
- if (prcNew)
- {
- hmon2 = MonitorFromRect(prcNew, MONITOR_DEFAULTTONULL);
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.sac new pos {%d,%d,%d,%d} on monitor %08X"), prcNew->left, prcNew->top, prcNew->right, prcNew->bottom, hmon2);
- if (hmon2 && (hmon2 != hmon1))
- {
- int iret = RecomputeWorkArea(hwndCause, hmon2, &rcWork2);
- if (iret == RWA_CHANGED)
- iChange |= 2;
- else if (iret == RWA_BOTTOMMOSTTRAY && (!iChange))
- iChange = 4;
- }
- }
- //
- // did the prcOld's display's work area change?
- //
- if (iChange & 1)
- {
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.sac changing work area for monitor %08X"), hmon1);
- // only send SENDWININICHANGE if the desktop has been created (otherwise
- // we will hang the explorer because the main thread is currently blocked)
- SystemParametersInfo(SPI_SETWORKAREA, TRUE, &rcWork1,
- (iChange == 1 && v_hwndDesktop)? SPIF_SENDWININICHANGE : 0);
- RedrawDesktop(&rcWork1);
- }
- //
- // did the prcOld's display's work area change?
- //
- if (iChange & 2)
- {
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.sac changing work area for monitor %08X"), hmon2);
- // only send SENDWININICHANGE if the desktop has been created (otherwise
- // we will hang the explorer because the main thread is currently blocked)
- SystemParametersInfo(SPI_SETWORKAREA, TRUE, &rcWork2,
- v_hwndDesktop ? SPIF_SENDWININICHANGE : 0);
- RedrawDesktop(&rcWork2);
- }
- // only send if the desktop has been created...
- // need to send if it's from the tray or any outside app that causes size change
- // from the tray because autohideness will affect desktop size even if it's not always on top
- if ((bTray || iChange == 4) && v_hwndDesktop )
- SendMessage(v_hwndDesktop, WM_SIZE, 0, 0);
- }
- void Tray_StuckTrayChange()
- {
- // We used to blow off the StuckAppChange when the tray was in autohide
- // mode, since moving or resizing an autohid tray doesn't change the
- // work area. Now we go ahead with the StuckAppChange in this case
- // too. The reason is that we can get into a state where the work area
- // size is incorrect, and we want the taskbar to always be self-repairing
- // in this case (so that resizing or moving the taskbar will correct the
- // work area size).
- //
- // pass a NULL window here since we don't want to hand out our window and
- // the tray doesn't get these anyway (nobody cares as long as its not them)
- //
- StuckAppChange(NULL, &g_ts.rcOldTray,
- &g_ts.arStuckRects[g_ts.uStuckPlace], TRUE);
- //
- // save off the new tray position...
- //
- g_ts.rcOldTray = g_ts.arStuckRects[g_ts.uStuckPlace];
- }
- UINT Tray_RecalcStuckPos(LPRECT prc)
- {
- RECT rcDummy;
- POINT pt;
- if (!prc)
- {
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.t_rsp no rect supplied, using window rect"));
- prc = &rcDummy;
- GetWindowRect(v_hwndTray, prc);
- }
- // use the center of the original drag rect as a staring point
- pt.x = prc->left + RECTWIDTH(*prc) / 2;
- pt.y = prc->top + RECTHEIGHT(*prc) / 2;
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.t_rsp rect is {%d, %d, %d, %d} point is {%d, %d}"), prc->left, prc->top, prc->right, prc->bottom, pt.x, pt.y);
- // reset this so the drag code won't give it preference
- g_ts.uMoveStuckPlace = (UINT)-1;
- // simulate a drag back to figure out where we originated from
- // you may be tempted to remove this. before you do think about dragging
- // the tray across monitors and then hitting ESC...
- return Tray_CalcDragPlace(pt);
- }
- /*------------------------------------------------------------------
- ** the position is changing in response to a move operation.
- **
- ** if the docking status changed, we need to get a new size and
- ** maybe a new frame style. change the WINDOWPOS to reflect
- ** these changes accordingly.
- **------------------------------------------------------------------*/
- void Tray_DoneMoving(LPWINDOWPOS lpwp)
- {
- RECT rc, *prc;
- if (g_ts.uMoveStuckPlace == (UINT)-1)
- return;
- if (g_ts.fSysSizing)
- g_ts._fDeferedPosRectChange = TRUE;
- rc.left = lpwp->x;
- rc.top = lpwp->y;
- rc.right = lpwp->x + lpwp->cx;
- rc.bottom = lpwp->y + lpwp->cy;
- prc = &g_ts.arStuckRects[g_ts.uMoveStuckPlace];
- if (!EqualRect(prc, &rc))
- {
- g_ts.uMoveStuckPlace = Tray_RecalcStuckPos(&rc);
- prc = &g_ts.arStuckRects[g_ts.uMoveStuckPlace];
- }
- // Get the new hmonitor
- g_ts.hmonStuck = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);
- if (g_ts.hwndView)
- Tray_HandleSizing(0, prc, g_ts.uMoveStuckPlace);
- lpwp->x = prc->left;
- lpwp->y = prc->top;
- lpwp->cx = RECTWIDTH(*prc);
- lpwp->cy = RECTHEIGHT(*prc);
- lpwp->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
- // if we were autohiding, we need to update our appbar autohide rect
- if (g_ts.uAutoHide & AH_ON)
- {
- // unregister us from the old side
- IAppBarSetAutoHideBar(v_hwndTray, FALSE, g_ts.uStuckPlace);
- }
- // All that work might've changed g_ts.uMoveStuckPlace (since there
- // was a lot of message traffic), so check one more time.
- // Somehow, NT Stress manages to get us in here with an invalid
- // uMoveStuckPlace.
- if (IsValidSTUCKPLACE(g_ts.uMoveStuckPlace))
- {
- // remember the new state
- g_ts.uStuckPlace = g_ts.uMoveStuckPlace;
- }
- g_ts.uMoveStuckPlace = (UINT)-1;
- BandSite_SetMode(g_ts.ptbs, STUCK_HORIZONTAL(g_ts.uStuckPlace) ? 0 : DBIF_VIEWMODE_VERTICAL);
- if ((g_ts.uAutoHide & AH_ON) &&
- !IAppBarSetAutoHideBar(v_hwndTray, TRUE, g_ts.uStuckPlace))
- {
- Tray_AutoHideCollision();
- }
- }
- UINT Tray_CalcDragPlace(POINT pt)
- {
- UINT uPlace = g_ts.uMoveStuckPlace;
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.t_cdp starting point is {%d, %d}"), pt.x, pt.y);
- //
- // if the mouse is currently over the tray position leave it alone
- //
- if ((uPlace == (UINT)-1) || !PtInRect(&g_ts.arStuckRects[uPlace], pt))
- {
- HMONITOR hmonDrag;
- SIZE screen, error;
- UINT uHorzEdge, uVertEdge;
- RECT rcDisplay, *prcStick;
- //
- // which display is the mouse on?
- //
- hmonDrag = Tray_GetDisplayRectFromPoint(&rcDisplay, pt,
- MONITOR_DEFAULTTOPRIMARY);
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.t_cdp monitor is %08X"), hmonDrag);
- //
- // re-origin at zero to make calculations simpler
- //
- screen.cx = RECTWIDTH(rcDisplay);
- screen.cy = RECTHEIGHT(rcDisplay);
- pt.x -= rcDisplay.left;
- pt.y -= rcDisplay.top;
- //
- // are we closer to the left or right side of this display?
- //
- if (pt.x < (screen.cx / 2))
- {
- uVertEdge = STICK_LEFT;
- error.cx = pt.x;
- }
- else
- {
- uVertEdge = STICK_RIGHT;
- error.cx = screen.cx - pt.x;
- }
- //
- // are we closer to the top or bottom side of this display?
- //
- if (pt.y < (screen.cy / 2))
- {
- uHorzEdge = STICK_TOP;
- error.cy = pt.y;
- }
- else
- {
- uHorzEdge = STICK_BOTTOM;
- error.cy = screen.cy - pt.y;
- }
- //
- // closer to a horizontal or vertical edge?
- //
- uPlace = ((error.cy * screen.cx) > (error.cx * screen.cy))?
- uVertEdge : uHorzEdge;
- // which StuckRect should we use?
- prcStick = &g_ts.arStuckRects[uPlace];
- //
- // need to recalc stuck rect for new monitor?
- //
- if ((hmonDrag != Tray_GetDisplayRectFromRect(NULL, prcStick,
- MONITOR_DEFAULTTONULL)))
- {
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.t_cdp re-snapping rect for new display"));
- Tray_MakeStuckRect(prcStick, &rcDisplay, g_ts.sStuckWidths, uPlace);
- }
- }
- DebugMsg(DM_TRAYDOCK, TEXT("TRAYDOCK.t_cdp edge is %d, rect is {%d, %d, %d, %d}"), uPlace, g_ts.arStuckRects[uPlace].left, g_ts.arStuckRects[uPlace].top, g_ts.arStuckRects[uPlace].right, g_ts.arStuckRects[uPlace].bottom);
- ASSERT(IsValidSTUCKPLACE(uPlace));
- return uPlace;
- }
- //------------------------------------------------------------------
- void Tray_HandleMoving(WPARAM wParam, LPRECT lprc)
- {
- POINT ptCursor;
- GetCursorPos(&ptCursor);
- g_ts.uMoveStuckPlace = Tray_CalcDragPlace(ptCursor);
- *lprc = g_ts.arStuckRects[g_ts.uMoveStuckPlace];
- Tray_HandleSizing(wParam, lprc, g_ts.uMoveStuckPlace);
- }
- //------------------------------------------------------------------
- // store the tray size when dragging is finished
- void Tray_SnapshotStuckRectSize(UINT uPlace)
- {
- RECT rcDisplay, *prc = &g_ts.arStuckRects[uPlace];
- //
- // record the width of this stuck rect
- //
- if (STUCK_HORIZONTAL(uPlace))
- g_ts.sStuckWidths.cy = RECTHEIGHT(*prc);
- else
- g_ts.sStuckWidths.cx = RECTWIDTH(*prc);
- //
- // we only present a horizontal or vertical size to the end user
- // so update the StuckRect on the other side of the screen to match
- //
- Tray_GetStuckDisplayRect(uPlace, &rcDisplay);
- uPlace += 2;
- uPlace %= 4;
- prc = &g_ts.arStuckRects[uPlace];
- Tray_MakeStuckRect(prc, &rcDisplay, g_ts.sStuckWidths, uPlace);
- }
- //------------------------------------------------------------------
- // Size the icon area to fill as much of the tray window as it can.
- //------------------------------------------------------------------
- void Tray_SizeWindows()
- {
- RECT rcView, rcClock, rcClient, rcDesktop;
- int fHiding;
- if (!g_ts.hwndRebar || !g_ts.hwndMain || !g_ts.hwndNotify)
- return;
- fHiding = (g_ts.uAutoHide & AH_HIDING);
- if (fHiding)
- {
- TrayShowWindow(SW_HIDE);
- }
- // remember our current size
- Tray_SnapshotStuckRectSize(g_ts.uStuckPlace);
- GetClientRect(g_ts.hwndMain, &rcClient);
- Tray_AlignStartButton();
- Tray_GetWindowSizes(&rcClient, &rcView, &rcClock, &rcDesktop);
- InvalidateRect(g_ts.hwndStart, NULL, TRUE);
- // position the view
- SetWindowPos(g_ts.hwndRebar, NULL, rcView.left, rcView.top,
- RECTWIDTH(rcView), RECTHEIGHT(rcView),