2025-11-28 00:35:46 +09:00

967 lines
26 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
#include <windows.h>
#include <windowsx.h>
#include <strsafe.h>
#include "resource.h"
#include "appbar.h"
#pragma comment(linker, "\"/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
/////////////////////////////////////////////////////////////////////////////
// Local Prototypes
static BOOL AppBar_AutoHide(HWND hwnd);
static BOOL AppBar_NoAutoHide(HWND hwnd);
static void SlideWindow(HWND hwnd, LPRECT prc);
/////////////////////////////////////////////////////////////////////////////
// Global Variables
HINSTANCE g_hInstance = NULL;
BOOL g_fAppRegistered = FALSE; // TRUE if the appbar is registered
RECT g_rcAppBar; // Current rect of the appbar
DWORD g_cxWidth, g_cyHeight;
const int g_dtSlideHide = 400;
const int g_dtSlideShow = 200;
//
// FUNCTION: AppBar_Size(HWND)
//
// PURPOSE: Handles updating the appbar's size and position.
//
// PARAMETERS:
// hwnd - handle of the appbar
//
// COMMENTS:
//
void AppBar_Size(HWND hwnd)
{
if (g_fAppRegistered)
{
POPTIONS pOpt = GetAppbarData(hwnd);
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hwnd;
RECT rc;
GetWindowRect(hwnd, &rc);
AppBar_QuerySetPos(pOpt->uSide, &rc, &abd, TRUE);
}
}
//
// FUNCTION: AppBar_QueryPos
//
// PURPOSE: Asks the system if the AppBar can occupy the rectangle specified
// in lprc. The system will change the lprc rectangle to make
// it a valid rectangle on the desktop.
//
// PARAMETERS:
// hwnd - Handle to the AppBar window.
// lprc - Rectange that the AppBar is requesting to occupy.
//
void AppBar_QueryPos(HWND hwnd, LPRECT lprc)
{
POPTIONS pOpt = GetAppbarData(hwnd);
// Fill out the APPBARDATA struct and save the edge we're moving to
// in the appbar OPTIONS struct.
APPBARDATA abd;
abd.hWnd = hwnd;
abd.cbSize = sizeof(APPBARDATA);
abd.rc = *lprc;
abd.uEdge = pOpt->uSide;
// Calculate the part we want to occupy. We only figure out the top
// and bottom coordinates if we're on the top or bottom of the screen.
// Likewise for the left and right. We will always try to occupy the
// full height or width of the screen edge.
int iWidth = 0;
int iHeight = 0;
if ((ABE_LEFT == abd.uEdge) || (ABE_RIGHT == abd.uEdge))
{
iWidth = abd.rc.right - abd.rc.left;
abd.rc.top = 0;
abd.rc.bottom = GetSystemMetrics(SM_CYSCREEN);
}
else
{
iHeight = abd.rc.bottom - abd.rc.top;
abd.rc.left = 0;
abd.rc.right = GetSystemMetrics(SM_CXSCREEN);
}
// Ask the system for the screen space
SHAppBarMessage(ABM_QUERYPOS, &abd);
// The system will return an approved position along the edge we're asking
// for. However, if we can't get the exact position requested, the system
// only updates the edge that's incorrect. For example, if we want to
// attach to the bottom of the screen and the taskbar is already there,
// we'll pass in a rect like 0, 964, 1280, 1024 and the system will return
// 0, 964, 1280, 996. Since the appbar has to be above the taskbar, the
// bottom of the rect was adjusted to 996. We need to adjust the opposite
// edge of the rectangle to preserve the height we want.
switch (abd.uEdge)
{
case ABE_LEFT:
abd.rc.right = abd.rc.left + iWidth;
break;
case ABE_RIGHT:
abd.rc.left = abd.rc.right - iWidth;
break;
case ABE_TOP:
abd.rc.bottom = abd.rc.top + iHeight;
break;
case ABE_BOTTOM:
abd.rc.top = abd.rc.bottom - iHeight;
break;
}
*lprc = abd.rc;
}
//
// FUNCTION: AppBar_QuerySetPos(UINT, LPRECT, PAPPBARDATA, BOOL)
//
// PURPOSE: Asks the system if the appbar can move itself to a particular
// side of the screen and then does move the appbar.
//
// PARAMETERS:
// uEdge - Side of the screen to move to. Can be ABE_TOP, ABE_BOTTOM,
// ABE_LEFT, or ABE_RIGHT.
// lprc - Screen rect the appbar wishes to occupy. This will be
// modified and will return the area the system will let the
// appbar occupy.
// pabd - Pointer to the APPBARDATA struct used in all appbar system
// calls.
// fMove - TRUE if the function should move the appbar, FALSE if the
// caller will move the AppBar.
//
void AppBar_QuerySetPos(UINT uEdge, LPRECT lprc, PAPPBARDATA pabd, BOOL fMove)
{
POPTIONS pOpt = GetAppbarData(pabd->hWnd);
// Fill out the APPBARDATA struct and save the edge we're moving to
// in the appbar OPTIONS struct.
pabd->rc = *lprc;
pabd->uEdge = uEdge;
pOpt->uSide = uEdge;
AppBar_QueryPos(pabd->hWnd, &(pabd->rc));
// Tell the system we're moving to this new approved position.
SHAppBarMessage(ABM_SETPOS, pabd);
if (fMove)
{
// Move the appbar window to the new position
MoveWindow(pabd->hWnd, pabd->rc.left, pabd->rc.top,
pabd->rc.right - pabd->rc.left,
pabd->rc.bottom - pabd->rc.top, TRUE);
}
// Save the appbar rect. We use this later when we autohide. If we're
// currently hidden, then don't mess with this.
if (!pOpt->fAutoHide)
{
g_rcAppBar = pabd->rc;
}
}
//
// FUNCTION: AppBar_PosChanged(PAPPBARDATA)
//
// PURPOSE: The system has changed our position for some reason. We need
// to recalculate the position on the screen we want to occupy
// by determining how wide or thick we are and the update the
// screen position.
//
//
// PARAMETERS:
// pabd - Pointer to the APPBARDATA structure used in all AppBar calls
// to the system.
//
void AppBar_PosChanged(PAPPBARDATA pabd)
{
// Start by getting the size of the screen.
RECT rc;
rc.top = 0;
rc.left = 0;
rc.right = GetSystemMetrics(SM_CXSCREEN);
rc.bottom = GetSystemMetrics(SM_CYSCREEN);
// Update the g_rcAppbar so when we slide (if hidden) we slide to the
// right place.
POPTIONS pOpt = GetAppbarData(pabd->hWnd);
if (pOpt->fAutoHide)
{
g_rcAppBar = rc;
switch (pOpt->uSide)
{
case ABE_TOP:
g_rcAppBar.bottom = g_rcAppBar.top + g_cyHeight;
break;
case ABE_BOTTOM:
g_rcAppBar.top = g_rcAppBar.bottom - g_cyHeight;
break;
case ABE_LEFT:
g_rcAppBar.right = g_rcAppBar.left + g_cxWidth;
break;
case ABE_RIGHT:
g_rcAppBar.left = g_rcAppBar.right - g_cxWidth;
break;
}
}
// Now get the current window rectangle and find the height and width
RECT rcWindow;
GetWindowRect(pabd->hWnd, &rcWindow);
int iHeight = rcWindow.bottom - rcWindow.top;
int iWidth = rcWindow.right - rcWindow.left;
// Depending on which side we're on, try to preserve the thickness of
// the window
switch (pOpt->uSide)
{
case ABE_TOP:
rc.bottom = rc.top + iHeight;
break;
case ABE_BOTTOM:
rc.top = rc.bottom - iHeight;
break;
case ABE_LEFT:
rc.right = rc.left + iWidth;
break;
case ABE_RIGHT:
rc.left = rc.right - iWidth;
break;
}
// Move the appbar.
AppBar_QuerySetPos(pOpt->uSide, &rc, pabd, TRUE);
}
//
// FUNCTION: AppBar_Callback(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Handles notification messages sent from the system to our
// appbar.
//
// PARAMETERS:
// hwnd - Handle of the appbar window receiving the notification.
// uMsg - The appbar notification message that we registered.
// wParam - Contains the specific notification code.
// lParam - Extra information dependant on the notification code.
//
void AppBar_Callback(HWND hwnd, UINT /* uMsg */, WPARAM wParam, LPARAM lParam)
{
static HWND hwndZOrder = NULL;
APPBARDATA abd;
abd.cbSize = sizeof(abd);
abd.hWnd = hwnd;
switch (wParam)
{
// Notifies the appbar that the taskbar's autohide or always-on-top
// state has changed. The appbar can use this to conform to the settings
// of the system taskbar.
case ABN_STATECHANGE:
break;
// Notifies the appbar when a full screen application is opening or
// closing. When a full screen app is opening, the appbar must drop
// to the bottom of the Z-Order. When the app is closing, we should
// restore our Z-order position.
case ABN_FULLSCREENAPP:
if (lParam)
{
// A full screen app is opening. Move us to the bottom of the
// Z-Order.
// First get the window that we're underneath so we can correctly
// restore our position
hwndZOrder = GetWindow(hwnd, GW_HWNDPREV);
// Now move ourselves to the bottom of the Z-Order
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
else
{
// The app is closing. Restore the Z-order
POPTIONS pOpt = GetAppbarData(hwnd);
SetWindowPos(hwnd, pOpt->fOnTop ? HWND_TOPMOST : hwndZOrder,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
hwndZOrder = NULL;
}
break;
// Notifies the appbar when an event has occured that may effect the
// appbar's size and position. These events include changes in the
// taskbar's size, position, and visiblity as well as adding, removing,
// or resizing another appbar on the same side of the screen.
case ABN_POSCHANGED:
// Update our position in response to the system change
AppBar_PosChanged(&abd);
break;
}
}
//
// FUNCTION: AppBar_Register(HWND)
//
// PURPOSE: Registers the appbar with the system.
//
// PARAMETERS:
// hwnd - handle of the appbar to register.
//
// RETURN VALUE:
// Returns TRUE if successful, FALSE otherwise.
//
// COMMENTS:
// Sets the system wide g_fAppRegistered variable.
//
BOOL AppBar_Register(HWND hwnd)
{
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hwnd;
abd.uCallbackMessage = APPBAR_CALLBACK;
g_fAppRegistered = (BOOL)SHAppBarMessage(ABM_NEW, &abd);
return g_fAppRegistered;
}
//
// FUNCTION: AppBar_UnRegister(HWND)
//
// PARAMETERS:
// hwnd - handle of the appbar to register.
//
// RETURN VALUE:
// Returns TRUE if successful, FALSE otherwise.
//
// COMMENTS:
// Sets the system wide g_fAppRegistered variable.
//
BOOL AppBar_UnRegister(HWND hwnd)
{
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hwnd;
g_fAppRegistered = !SHAppBarMessage(ABM_REMOVE, &abd);
return !g_fAppRegistered;
}
//
// FUNCTION: AppBar_SetAutoHide(HWND, BOOL)
//
// PURPOSE: Causes the appbar window to either auto hide or stop auto
// hiding.
//
// PARAMETERS:
// hwnd - Handle of the appbar window to change the auto hide state.
// fHide - TRUE if we want the window to autohide, FALSE to stop.
//
// RETURN VALUE:
// Returns TRUE if successful, FALSE otherwise.
//
BOOL AppBar_SetAutoHide(HWND hwnd, BOOL fHide)
{
if (fHide)
{
return AppBar_AutoHide(hwnd);
}
else
{
return AppBar_NoAutoHide(hwnd);
}
}
//
// FUNCTION: AppBar_AutoHide(HWND)
//
// PURPOSE: Does the work of changing the appbar to autohide. We check
// to see if we can autohide, and if so unregister and tell
// the system we are autohiding.
//
// PARAMETERS:
// hwnd - Window handle of the appbar.
//
// RETURN VALUE:
// TRUE if successful, FALSE otherwise.
//
BOOL AppBar_AutoHide(HWND hwnd)
{
POPTIONS pOpt = GetAppbarData(hwnd);
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hwnd;
abd.uEdge = pOpt->uSide;
// First figure out if someone already has this side for
// autohiding
HWND hwndAutoHide = (HWND) SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd);
if (hwndAutoHide != NULL)
{
return FALSE;
}
// We can autohide on this edge. Set the autohide style.
abd.lParam = TRUE;
BOOL fSuccess = (BOOL) SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd);
if (!fSuccess)
{
ErrorHandler();
return FALSE;
}
else
{
// Since we're allowed to autohide, we need to adjust our screen
// rectangle to the autohidden position. This will allow the system
// to resize the desktop.
pOpt->fAutoHide = TRUE;
g_cxWidth = pOpt->cxWidth;
g_cyHeight = pOpt->cyHeight;
RECT rc;
rc = g_rcAppBar;
switch (pOpt->uSide)
{
case ABE_TOP:
rc.bottom = rc.top + 2;
break;
case ABE_BOTTOM:
rc.top = rc.bottom - 2;
break;
case ABE_LEFT:
rc.right = rc.left + 2;
break;
case ABE_RIGHT:
rc.left = rc.right - 2;
break;
}
AppBar_QuerySetPos(pOpt->uSide, &rc, &abd, TRUE);
}
return TRUE;
}
//
// FUNCTION: AppBar_NoAutoHide(HWND)
//
// PURPOSE: Does the work of changing the appbar to no-autohide. We
// check to make sure we are actually auto hiding, and if so
// re-register the appbar to get our desktop scren space back.
//
// PARAMETERS:
// hwnd - Window handle of the appbar.
//
// RETURN VALUE:
// TRUE if successful, FALSE otherwise.
//
BOOL AppBar_NoAutoHide(HWND hwnd)
{
POPTIONS pOpt = GetAppbarData(hwnd);
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hwnd;
abd.uEdge = pOpt->uSide;
// First let's check to see if we're the appbar attached to the
// side of the screen
abd.uEdge = pOpt->uSide;
HWND hwndAutoHide = (HWND) SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd);
if (hwndAutoHide != hwnd)
{
return FALSE;
}
// We can autohide or stop autohide on this edge. Set the autohide style.
abd.lParam = FALSE;
BOOL fSuccess = (BOOL) SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd);
if (!fSuccess)
{
ErrorHandler();
return FALSE;
}
else
{
// Need to change the appbar to get the screen desktop space
// back. Also need to reattach the appbar to that edge of the
// screen.
pOpt->fAutoHide = FALSE;
pOpt->cxWidth = g_cxWidth;
pOpt->cyHeight = g_cyHeight;
AppBar_SetSide(hwnd, pOpt->uSide);
}
return TRUE;
}
//
// FUNCTION: AppBar_SetSide(HWND, UINT)
//
// PURPOSE: Sets the side the AppBar is currently attached to.
//
// PARAMETERS:
// hwnd - Window handle of the appbar.
// uSide - Side of the screen to attach to. Can be ABE_TOP, ABE_BOTTOM,
// ABE_LEFT, or ABE_RIGHT.
//
// RETURN VALUE:
// TRUE if successful, FALSE otherwise.
//
BOOL AppBar_SetSide(HWND hwnd, UINT uSide)
{
// Calculate the size of the screen so we can occupy the full width or
// height of the screen on the edge we request.
RECT rc;
rc.top = 0;
rc.left = 0;
rc.right = GetSystemMetrics(SM_CXSCREEN);
rc.bottom = GetSystemMetrics(SM_CYSCREEN);
// Fill out the APPBARDATA struct with the basic information
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hwnd;
// If the appbar is autohidden, turn that off so we can move the bar
BOOL fAutoHide = FALSE;
POPTIONS pOpt = GetAppbarData(hwnd);
if (pOpt->fAutoHide)
{
fAutoHide = pOpt->fAutoHide;
// Turn off the redrawing of the desktop while we move things around.
// If you put any breakpoints in this area you will lock up the desktop
// Since turning off the desktop repaints turns it off for all the apps
// in the system
SetWindowRedraw(GetDesktopWindow(), FALSE);
AppBar_SetAutoHide(hwnd, FALSE);
pOpt->fHiding = FALSE;
}
// Adjust the rectangle to set our height or width depending on the
// side we want.
switch (uSide)
{
case ABE_TOP:
rc.bottom = rc.top + pOpt->cyHeight;
break;
case ABE_BOTTOM:
rc.top = rc.bottom - pOpt->cyHeight;
break;
case ABE_LEFT:
rc.right = rc.left + pOpt->cxWidth;
break;
case ABE_RIGHT:
rc.left = rc.right - pOpt->cxWidth;
break;
}
// Move the appbar to the new screen space.
AppBar_QuerySetPos(uSide, &rc, &abd, TRUE);
// If the appbar was hidden, rehide it now
if (fAutoHide)
{
AppBar_SetAutoHide(hwnd, TRUE);
pOpt->fHiding = TRUE;
SetWindowRedraw(GetDesktopWindow(), TRUE);
RedrawWindow(GetDesktopWindow(), NULL, NULL,
RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
}
return TRUE;
}
//
// FUNCTION: AppBar_SetAlwaysOnTop(HWND, BOOL)
//
// PURPOSE: Sets the Always-On-Top state for the appbar.
//
// PARAMETERS:
// hwnd - Window handle of the AppBar to set the state for.
// fOnTop - TRUE to set the AppBar to Always-On-Top, FALSE otherwise
//
void AppBar_SetAlwaysOnTop(HWND hwnd, BOOL fOnTop)
{
POPTIONS pOpt = GetAppbarData(hwnd);
// Update the window position to HWND_TOPMOST if we're to be always
// on top, or HWND_NOTOPMOST if we're not.
SetWindowPos(hwnd, (fOnTop) ? HWND_TOPMOST : HWND_NOTOPMOST,
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
// Store the setting in the appbar OPTIONS struct.
pOpt->fOnTop = fOnTop;
}
//
// FUNCTION: AppBar_Hide(HWND)
//
// PURPOSE: Causes the appbar to hide itself.
//
// PARAMETERS:
// hwnd - Handle of the AppBar to hide.
//
void AppBar_Hide(HWND hwnd)
{
POPTIONS pOpt = GetAppbarData(hwnd);
// Don't want to hide if AutoHide not set
if (!pOpt->fAutoHide)
{
return;
}
// Calculate a hidden rectangle to use
RECT rc = g_rcAppBar;
switch (pOpt->uSide)
{
case ABE_TOP:
rc.bottom = rc.top + 2;
break;
case ABE_BOTTOM:
rc.top = rc.bottom - 2;
break;
case ABE_LEFT:
rc.right = rc.left + 2;
break;
case ABE_RIGHT:
rc.left = rc.right - 2;
break;
}
pOpt->fHiding = TRUE;
SlideWindow(hwnd, &rc);
}
//
// FUNCTION: AppBar_UnHide(HWND)
//
// PURPOSE: Causes a hidden appbar to unhide itself.
//
// PARAMETERS:
// hwnd - Handle of the appbar to unhide.
//
void AppBar_UnHide(HWND hwnd)
{
POPTIONS pOpt = GetAppbarData(hwnd);
SlideWindow(hwnd, &g_rcAppBar);
pOpt->fHiding = FALSE;
AppBar_SetAutoHideTimer(hwnd);
}
//
// FUNCTION: AppBar_SetAutoHideTimer(HWND)
//
// PURPOSE: Starts the auto hide timer.
//
// PARAMETERS:
// hwnd - Handle of the appbar to set the timer for.
//
// COMMENTS:
// This is called to cause a delay between when the user's mouse leaves
// the appbar area and the appbar is slid off the screen.
//
void AppBar_SetAutoHideTimer(HWND hwnd)
{
POPTIONS pOpt = GetAppbarData(hwnd);
if (pOpt->fAutoHide)
{
SetTimer(hwnd, IDT_AUTOHIDE, 500, NULL);
}
}
//
// FUNCTION: AppBar_SetAutoUnhideTimer(HWND)
//
// PURPOSE: Starts the auto-UNhide timer.
//
// PARAMETERS:
// hwnd - Handle of the appbar to set the timer for.
//
// COMMENTS:
// This is called to cause a delay between the time where the mouse enters
// the appbar window and the time where the appbar displays itself.
//
void AppBar_SetAutoUnhideTimer(HWND hwnd)
{
POPTIONS pOpt = GetAppbarData(hwnd);
if (pOpt->fAutoHide && pOpt->fHiding)
{
SetTimer(hwnd, IDT_AUTOUNHIDE, 50, NULL);
}
}
//
// FUNCTION: GetAppbarData(HWND)
//
// PURPOSE: Retrieves a pointer to the OPTIONS structure stored in the
// window's extra bytes.
//
// PARAMETERS:
// hwnd - Handle of the window to retrieve the pointer from.
//
// RETURN VALUE:
// Returns a pointer to an OPTIONS struct
//
POPTIONS GetAppbarData(HWND hwnd)
{
return (POPTIONS) GetWindowLongPtr(hwnd, 0);
}
//
// FUNCTION: SlideWindow(HWND, LPRECT)
//
// PURPOSE: Slides the AppBar off the edge of the screen when the AppBar
// has the AutoHide state set.
//
// PARAMETERS:
// hwnd - handle of the window to scroll off the screen
// prc - rectangle you wish the appbar to occupy
//
// COMMENTS:
//
void SlideWindow(HWND hwnd, LPRECT prc)
{
RECT rcNew = *prc;
RECT rcOld;
GetWindowRect(hwnd, &rcOld);
BOOL fShow = (rcNew.bottom - rcNew.top) > (rcOld.bottom - rcOld.top) ||
(rcNew.right - rcNew.left) > (rcOld.right - rcOld.left);
int dx = (rcNew.right - rcOld.right) + (rcNew.left - rcOld.left);
int dy = (rcNew.bottom - rcOld.bottom) + (rcNew.top - rcOld.top);
int dt;
if (fShow)
{
rcOld = rcNew;
OffsetRect(&rcOld, -dx, -dy);
SetWindowPos(hwnd, NULL, rcOld.left, rcOld.top,
rcOld.right - rcOld.left, rcOld.bottom - rcOld.top,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME);
dt = g_dtSlideShow;
}
else
{
dt = g_dtSlideHide;
}
HANDLE hThreadMe = GetCurrentThread();
int priority = GetThreadPriority(hThreadMe);
SetThreadPriority(hThreadMe, THREAD_PRIORITY_HIGHEST);
int t, t0 = GetTickCount();
while ((t = GetTickCount()) < t0 + dt)
{
int x = rcOld.left + dx * (t - t0) / dt;
int y = rcOld.top + dy * (t - t0) / dt;
SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
if (fShow)
{
UpdateWindow(hwnd);
}
else
{
UpdateWindow(GetDesktopWindow());
}
}
SetThreadPriority(hThreadMe, priority);
SetWindowPos(hwnd, NULL, rcNew.left, rcNew.top,
rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME);
}
//
// FUNCTION: ErrorHandlerEx(INT, LPSTR)
//
// PURPOSE: Reports that an error has occurred.
//
// PARAMETERS:
// wLine - Source file line number
// pszFile - Source file path
//
void ErrorHandlerEx( INT wLine, LPSTR pszFile )
{
// Get the text of the error message
LPWSTR pszMessage;
DWORD dwError = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPWSTR)&pszMessage,
0,
NULL);
// Check to see if an error occured calling FormatMessage()
WCHAR szBuffer[256];
if (0 == dwError)
{
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), L"An error occured calling FormatMessage(). Error Code %d", GetLastError());
MessageBoxW(NULL, szBuffer, L"Generic", MB_ICONSTOP | MB_ICONEXCLAMATION);
}
else
{
// Display the error message
StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), L"Generic, Line=%d, File=%s", wLine, pszFile);
MessageBox(NULL, pszMessage, szBuffer, MB_ICONEXCLAMATION | MB_OK);
}
}
//
// FUNCTION: wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
//
// PURPOSE: Main entry point of the AppBar sample application. Creates
// the appbar window and pumps messages.
//
// PARAMETERS:
// hInstance - Instance handle of the application
// (others are unused)
//
// RETURN VALUE:
// Process exit code.
//
int PASCAL wWinMain(HINSTANCE hInstance,
HINSTANCE /* hPrevInstance */,
LPWSTR /* lpszCmdLine */,
int /* nCmdShow */)
{
g_hInstance = hInstance;
WCHAR const szWindowClass[] = L"MSSampleAppbar"; // The main window class name
WNDCLASSEX wcex = { sizeof(wcex) };
wcex.lpfnWndProc = MainWndProc;
wcex.hInstance = g_hInstance;
wcex.cbWndExtra = sizeof(LPVOID);
wcex.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_APPICON));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_APPICON),
IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
0);
RegisterClassEx(&wcex);
// Create a main window for this application instance
HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_TOOLWINDOW,
szWindowClass,
L"Win32 Sample AppBar",
WS_POPUP | WS_THICKFRAME | WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
400,
200,
NULL,
NULL,
hInstance,
NULL
);
// If the window was successfully created, make the window visible,
// update its client area, and return "success". If the window
// was not created, return "failure"
int iResult = -1;
if (hwnd)
{
ShowWindow(hwnd, SW_SHOWDEFAULT); // Set to visible & paint non-client area
UpdateWindow(hwnd); // Tell window to paint client area
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg); // Translates virtual key codes
DispatchMessage(&msg); // Dispatches message to window procedure
}
iResult = ((int)msg.wParam);
}
return iResult;
}