755 lines
22 KiB
C
755 lines
22 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.
|
||
|
||
PROGRAM: Leakybin.c
|
||
|
||
PURPOSE: Illustrates the use of Windows NT application performance
|
||
counters to measure GlobalAlloc usage
|
||
|
||
PLATFORMS: Windows NT only
|
||
|
||
FUNCTIONS:
|
||
WinMain() - calls initialization function, processes message loop
|
||
InitApplication() - Initializes window data nd registers window
|
||
InitInstance() -saves instance handle and creates main window
|
||
WindProc() Processes messages
|
||
About() - Process menssages for "About" dialog box
|
||
MyRegisterClass() - Registers the application's window class
|
||
CenterWindow() - Centers one window over another
|
||
|
||
-----------------------------------------------------------------------*/
|
||
#define APPNAME "Leakybin"
|
||
|
||
// Windows Header Files:
|
||
#include <windows.h>
|
||
|
||
// C RunTime Header Files
|
||
#include <stdlib.h>
|
||
#include <malloc.h>
|
||
#include <memory.h>
|
||
#include <stdio.h>
|
||
|
||
// Local Header Files
|
||
#include "leakybin.h"
|
||
|
||
// Makes it easier to determine appropriate code paths:
|
||
#define IS_WIN32 TRUE
|
||
#define IS_NT IS_WIN32 && (BOOL)(GetVersion() < 0x80000000)
|
||
|
||
// Global Variables:
|
||
|
||
HINSTANCE hInst; // current instance
|
||
char szAppName[100]; // Name of the app
|
||
char szTitle[100]; // The title bar text
|
||
|
||
static UINT_PTR TimerID = 0;
|
||
static BOOL TimerRunning = FALSE;
|
||
static HMENU hAppMenu, hTestMenu;
|
||
static MEMORY_ALLOC_BLOCK mabListHead = {NULL};
|
||
|
||
// Foward declarations of functions included in this code module:
|
||
|
||
ATOM MyRegisterClass(CONST WNDCLASS*);
|
||
BOOL InitApplication(HINSTANCE);
|
||
BOOL InitInstance(HINSTANCE, int);
|
||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
|
||
BOOL CenterWindow (HWND, HWND);
|
||
LPTSTR GetStringRes (int id);
|
||
|
||
|
||
//
|
||
// FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
|
||
//
|
||
// PURPOSE: Entry point for the application.
|
||
//
|
||
// COMMENTS:
|
||
//
|
||
// This function initializes the application and processes the
|
||
// message loop.
|
||
//
|
||
int APIENTRY WinMain(HINSTANCE hInstance,
|
||
HINSTANCE hPrevInstance,
|
||
LPSTR lpCmdLine,
|
||
int nCmdShow
|
||
)
|
||
{
|
||
MSG msg;
|
||
HANDLE hAccelTable;
|
||
|
||
// Initialize global strings
|
||
strncpy_s(szAppName, 100, APPNAME, _TRUNCATE);
|
||
LoadString (hInstance, IDS_APP_TITLE, szTitle, 100);
|
||
|
||
if (! hPrevInstance)
|
||
{
|
||
// Perform instance initialization:
|
||
if (! InitApplication(hInstance))
|
||
{
|
||
return (FALSE);
|
||
}
|
||
}
|
||
|
||
// Perform application initialization:
|
||
if (! InitInstance(hInstance, nCmdShow))
|
||
{
|
||
return (FALSE);
|
||
}
|
||
|
||
hAccelTable = LoadAccelerators(hInstance, szAppName);
|
||
|
||
// Main message loop:
|
||
while (GetMessage(& msg, NULL, 0, 0))
|
||
{
|
||
if (! TranslateAccelerator(msg.hwnd, hAccelTable, & msg))
|
||
{
|
||
TranslateMessage(& msg);
|
||
DispatchMessage(& msg);
|
||
}
|
||
}
|
||
|
||
return (int) (msg.wParam);
|
||
|
||
lpCmdLine; // This will prevent 'unused formal parameter' warnings
|
||
}
|
||
|
||
//
|
||
// FUNCTION: MyRegisterClass(CONST WNDCLASS*)
|
||
//
|
||
// PURPOSE: Registers the window class.
|
||
//
|
||
// COMMENTS:
|
||
//
|
||
// This function and its usage is only necessary if you want this code
|
||
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
|
||
// function that was added to Windows 95. It is important to call this function
|
||
// so that the application will get 'well formed' small icons associated
|
||
// with it.
|
||
//
|
||
ATOM MyRegisterClass(CONST WNDCLASS *lpwc)
|
||
{
|
||
HANDLE hMod;
|
||
FARPROC proc;
|
||
WNDCLASSEX wcex;
|
||
|
||
hMod = GetModuleHandle ("USER32");
|
||
if (hMod != NULL)
|
||
{
|
||
|
||
#if defined (UNICODE)
|
||
proc = GetProcAddress (hMod, "RegisterClassExW");
|
||
#else
|
||
proc = GetProcAddress (hMod, "RegisterClassExA");
|
||
#endif
|
||
|
||
if (proc != NULL)
|
||
{
|
||
|
||
wcex.style = lpwc->style;
|
||
wcex.lpfnWndProc = lpwc->lpfnWndProc;
|
||
wcex.cbClsExtra = lpwc->cbClsExtra;
|
||
wcex.cbWndExtra = lpwc->cbWndExtra;
|
||
wcex.hInstance = lpwc->hInstance;
|
||
wcex.hIcon = lpwc->hIcon;
|
||
wcex.hCursor = lpwc->hCursor;
|
||
wcex.hbrBackground = lpwc->hbrBackground;
|
||
wcex.lpszMenuName = lpwc->lpszMenuName;
|
||
wcex.lpszClassName = lpwc->lpszClassName;
|
||
|
||
// Added elements for Windows 95:
|
||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||
wcex.hIconSm = LoadIcon(wcex.hInstance, "SMALL");
|
||
|
||
return (ATOM)((*proc)(&wcex));//return RegisterClassEx(&wcex) with type ATOM;
|
||
}
|
||
}
|
||
return (RegisterClass(lpwc));
|
||
}
|
||
|
||
|
||
//
|
||
// FUNCTION: InitApplication(HANDLE)
|
||
//
|
||
// PURPOSE: Initializes window data and registers window class
|
||
//
|
||
// COMMENTS:
|
||
//
|
||
// In this function, we initialize a window class by filling out a data
|
||
// structure of type WNDCLASS and calling either RegisterClass or
|
||
// the internal MyRegisterClass.
|
||
//
|
||
BOOL InitApplication(HINSTANCE hInstance)
|
||
{
|
||
WNDCLASS wc;
|
||
|
||
// Fill in window class structure with parameters that describe
|
||
// the main window.
|
||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||
wc.lpfnWndProc = (WNDPROC)WndProc;
|
||
wc.cbClsExtra = 0;
|
||
wc.cbWndExtra = 0;
|
||
wc.hInstance = hInstance;
|
||
wc.hIcon = LoadIcon (hInstance, szAppName);
|
||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
||
wc.lpszMenuName = szAppName;
|
||
wc.lpszClassName = szAppName;
|
||
|
||
// Register the window class and return success/failure code.
|
||
return RegisterClass(&wc);
|
||
}
|
||
|
||
//
|
||
// FUNCTION: InitInstance(HANDLE, int)
|
||
//
|
||
// PURPOSE: Saves instance handle and creates main window
|
||
//
|
||
// COMMENTS:
|
||
//
|
||
// In this function, we save the instance handle in a global variable and
|
||
// create and display the main program window.
|
||
//
|
||
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
|
||
{
|
||
HWND hWnd;
|
||
|
||
hInst = hInstance; // Store instance handle in our global variable
|
||
|
||
hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW,
|
||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
|
||
NULL, NULL, hInstance, NULL);
|
||
|
||
if (!hWnd)
|
||
{
|
||
return (FALSE);
|
||
}
|
||
|
||
ShowWindow(hWnd, nCmdShow);
|
||
UpdateWindow(hWnd);
|
||
|
||
return (TRUE);
|
||
}
|
||
void FreeAllocatedMemory()
|
||
{
|
||
{
|
||
PMEMORY_ALLOC_BLOCK pNextMab, pMab;
|
||
|
||
pMab = mabListHead.pNext;
|
||
|
||
while (pMab != NULL)
|
||
{
|
||
pNextMab = pMab->pNext;
|
||
G_FREE (pMab);
|
||
pMab = pNextMab;
|
||
}
|
||
|
||
mabListHead.pNext = NULL;
|
||
}
|
||
}
|
||
//
|
||
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
|
||
//
|
||
// PURPOSE: Processes messages for the main window.
|
||
//
|
||
// MESSAGES:
|
||
//
|
||
// WM_COMMAND - process the application menu
|
||
// WM_PAINT - Paint the main window
|
||
// WM_DESTROY - post a quit message and return
|
||
// WM_DISPLAYCHANGE - message sent to Plug & Play systems when the display changes
|
||
// WM_RBUTTONDOWN - Right mouse click -- put up context menu here if appropriate
|
||
// WM_NCRBUTTONUP - User has clicked the right button on the application's system menu
|
||
//
|
||
//
|
||
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
int wmId, wmEvent;
|
||
PAINTSTRUCT ps;
|
||
HDC hdc;
|
||
POINT pnt;
|
||
HMENU hMenu;
|
||
BOOL bGotHelp;
|
||
|
||
switch (message)
|
||
{
|
||
case WM_CREATE:
|
||
// clear timer flags
|
||
TimerID = 0;
|
||
TimerRunning = FALSE;
|
||
|
||
// enable "Start" menu selection
|
||
hAppMenu = GetMenu (hWnd);
|
||
hTestMenu = GetSubMenu (hAppMenu, 1);
|
||
EnableMenuItem (hTestMenu, IDM_STOP, MF_BYCOMMAND | MF_GRAYED);
|
||
EnableMenuItem (hTestMenu, IDM_START, MF_BYCOMMAND | MF_ENABLED);
|
||
break;
|
||
|
||
case WM_COMMAND:
|
||
wmId = LOWORD(wParam); // Remember, these are...
|
||
wmEvent = HIWORD(wParam); // ...different for Win32!
|
||
|
||
//Parse the menu selections:
|
||
switch (wmId)
|
||
{
|
||
|
||
case IDM_EXIT:
|
||
DestroyWindow (hWnd);
|
||
break;
|
||
|
||
case IDM_START:
|
||
if (!TimerRunning)
|
||
{
|
||
TimerID = SetTimer (hWnd, LEAK_TIMER, TIME_INTERVAL, NULL);
|
||
if (TimerID != 0)
|
||
{
|
||
TimerRunning = TRUE;
|
||
EnableMenuItem (hTestMenu, IDM_START,
|
||
MF_BYCOMMAND | MF_GRAYED);
|
||
EnableMenuItem (hTestMenu, IDM_STOP,
|
||
MF_BYCOMMAND | MF_ENABLED);
|
||
}
|
||
else
|
||
{
|
||
//unable to start timer
|
||
MessageBeep (MB_ICONEXCLAMATION);
|
||
}
|
||
}
|
||
InvalidateRect (hWnd, NULL, TRUE);
|
||
break;
|
||
|
||
case IDM_STOP:
|
||
if (TimerRunning)
|
||
{
|
||
KillTimer (hWnd, LEAK_TIMER);
|
||
TimerID = 0;
|
||
TimerRunning = FALSE;
|
||
EnableMenuItem (hTestMenu, IDM_STOP,
|
||
MF_BYCOMMAND | MF_GRAYED);
|
||
EnableMenuItem (hTestMenu, IDM_START,
|
||
MF_BYCOMMAND | MF_ENABLED);
|
||
}
|
||
InvalidateRect (hWnd, NULL, TRUE);
|
||
break;
|
||
|
||
case IDM_RESET:
|
||
FreeAllocatedMemory();
|
||
InvalidateRect (hWnd, NULL, TRUE);
|
||
break;
|
||
|
||
case IDM_ABOUT:
|
||
DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)About);
|
||
break;
|
||
|
||
case IDM_HELPTOPICS: // Only called in Windows 95
|
||
bGotHelp = WinHelp (hWnd, APPNAME".HLP", HELP_FINDER,(DWORD)0);
|
||
if (!bGotHelp)
|
||
{
|
||
MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
|
||
szAppName, MB_OK|MB_ICONHAND);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
return (DefWindowProc(hWnd, message, wParam, lParam));
|
||
}
|
||
break;
|
||
|
||
case WM_TIMER:
|
||
{
|
||
PMEMORY_ALLOC_BLOCK pMab, pNewMab;
|
||
|
||
pNewMab = (PMEMORY_ALLOC_BLOCK)G_ALLOC (GPTR, ALLOCATION_SIZE);
|
||
|
||
if (pNewMab != NULL)
|
||
{
|
||
// save this pointer
|
||
pNewMab->pNext = NULL;
|
||
if (mabListHead.pNext == NULL)
|
||
{
|
||
// this is the first entry
|
||
mabListHead.pNext = pNewMab;
|
||
}
|
||
else
|
||
{
|
||
// go to end of list
|
||
pMab = mabListHead.pNext;
|
||
while (pMab->pNext != NULL) pMab = pMab->pNext;
|
||
pMab->pNext = pNewMab;
|
||
}
|
||
InvalidateRect (hWnd, NULL, TRUE);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case WM_RBUTTONDOWN: // RightClick in windows client area...
|
||
pnt.x = LOWORD(lParam);
|
||
pnt.y = HIWORD(lParam);
|
||
ClientToScreen(hWnd, (LPPOINT) &pnt);
|
||
// This is where you would determine the appropriate 'context'
|
||
// menu to bring up. Since this app has no real functionality,
|
||
// we will just bring up the 'Help' menu:
|
||
hMenu = GetSubMenu (GetMenu (hWnd), 2);
|
||
if (hMenu)
|
||
{
|
||
TrackPopupMenu (hMenu, 0, pnt.x, pnt.y, 0, hWnd, NULL);
|
||
}
|
||
else
|
||
{
|
||
// Couldn't find the menu...
|
||
MessageBeep(0);
|
||
}
|
||
break;
|
||
|
||
|
||
case WM_DISPLAYCHANGE: // Only comes through on plug'n'play systems
|
||
{
|
||
SIZE szScreen;
|
||
DWORD dwBitsPerPixel = (DWORD)wParam;
|
||
|
||
szScreen.cx = LOWORD(lParam);
|
||
szScreen.cy = HIWORD(lParam);
|
||
|
||
MessageBox (GetFocus(), GetStringRes(IDS_DISPLAYCHANGED),
|
||
szAppName, 0);
|
||
}
|
||
break;
|
||
|
||
case WM_PAINT:
|
||
{
|
||
MEMORYSTATUS MemoryStatusData;
|
||
LONGLONG llInUse;
|
||
DWORD dwPercentUsed;
|
||
|
||
int nX, nY;
|
||
LONG lTextOutReturn;
|
||
int nStringLength;
|
||
CHAR szOutputString[100];
|
||
|
||
hdc = BeginPaint (hWnd, &ps);
|
||
// Add any drawing code here...
|
||
GlobalMemoryStatus (& MemoryStatusData);
|
||
|
||
llInUse = (LONGLONG)(MemoryStatusData.dwTotalPageFile -
|
||
MemoryStatusData.dwAvailPageFile + 5 );
|
||
llInUse *= 1000;
|
||
llInUse /= MemoryStatusData.dwTotalPageFile;
|
||
llInUse /= 10;
|
||
|
||
dwPercentUsed = (DWORD)llInUse;
|
||
|
||
nX = 0;
|
||
nY = 0;
|
||
_snprintf_s(szOutputString, 100, _TRUNCATE, "Reported Memory Load: \t%3.1d%%",
|
||
MemoryStatusData.dwMemoryLoad);
|
||
nStringLength = lstrlen (szOutputString) * sizeof (CHAR);
|
||
lTextOutReturn = TabbedTextOut (hdc, nX, nY,
|
||
szOutputString, nStringLength, 0, NULL, 0);
|
||
nY += HIWORD (lTextOutReturn);
|
||
|
||
_snprintf_s(szOutputString, 100, _TRUNCATE, "Page file in use: \t%3.1d%%",
|
||
dwPercentUsed);
|
||
nStringLength = lstrlen (szOutputString) * sizeof (CHAR);
|
||
lTextOutReturn = TabbedTextOut(hdc, nX, nY,
|
||
szOutputString, nStringLength, 0, NULL, 0);
|
||
nY += HIWORD(lTextOutReturn);
|
||
|
||
EndPaint (hWnd, &ps);
|
||
}
|
||
break;
|
||
|
||
case WM_DESTROY:
|
||
FreeAllocatedMemory();
|
||
// Tell WinHelp we don't need it any more...
|
||
WinHelp(hWnd, APPNAME".HLP", HELP_QUIT,(DWORD)0);
|
||
PostQuitMessage(0);
|
||
break;
|
||
|
||
default:
|
||
return (DefWindowProc(hWnd, message, wParam, lParam));
|
||
}
|
||
return (0);
|
||
}
|
||
|
||
//
|
||
// FUNCTION: About(HWND, unsigned, WORD, LONG)
|
||
//
|
||
// PURPOSE: Processes messages for "About" dialog box
|
||
// This version allows greater flexibility over the contents of the 'About' box,
|
||
// by pulling out values from the 'Version' resource.
|
||
//
|
||
// MESSAGES:
|
||
//
|
||
// WM_INITDIALOG - initialize dialog box
|
||
// WM_COMMAND - Input received
|
||
//
|
||
//
|
||
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
static HFONT hfontDlg; // Font for dialog text
|
||
static HFONT hFinePrint; // Font for 'fine print' in dialog
|
||
DWORD dwVerInfoSize; // Size of version information block
|
||
LPSTR lpVersion; // String pointer to 'version' text
|
||
DWORD dwVerHnd=0; // An 'ignored' parameter, always '0'
|
||
UINT uVersionLen;
|
||
BOOL bRetCode;
|
||
int i;
|
||
char szFullPath[256];
|
||
char szResult[256];
|
||
char szGetName[256];
|
||
DWORD dwVersion;
|
||
char szVersion[40];
|
||
DWORD dwResult;
|
||
|
||
switch (message)
|
||
{
|
||
case WM_INITDIALOG:
|
||
ShowWindow (hDlg, SW_HIDE);
|
||
|
||
if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE)
|
||
{
|
||
hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, 0, 0, 0,
|
||
VARIABLE_PITCH | FF_DONTCARE, "");
|
||
hFinePrint = CreateFont(11, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, 0, 0, 0,
|
||
VARIABLE_PITCH | FF_DONTCARE, "");
|
||
}
|
||
else
|
||
{
|
||
hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
VARIABLE_PITCH | FF_SWISS, "");
|
||
hFinePrint = CreateFont(11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
VARIABLE_PITCH | FF_SWISS, "");
|
||
}
|
||
|
||
CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
|
||
GetModuleFileName (hInst, szFullPath, sizeof(szFullPath));
|
||
|
||
// Now lets dive in and pull out the version information:
|
||
dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
|
||
if (dwVerInfoSize)
|
||
{
|
||
LPSTR lpstrVffInfo;
|
||
HANDLE hMem;
|
||
hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
|
||
lpstrVffInfo = GlobalLock(hMem);
|
||
GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
|
||
// The below 'hex' value looks a little confusing, but
|
||
// essentially what it is, is the hexidecimal representation
|
||
// of a couple different values that represent the language
|
||
// and character set that we are wanting string values for.
|
||
// 040904E4 is a very common one, because it means:
|
||
// US English, Windows MultiLingual characterset
|
||
// Or to pull it all apart:
|
||
// 04------ = SUBLANG_ENGLISH_USA
|
||
// --09---- = LANG_ENGLISH
|
||
// --11---- = LANG_JAPANESE
|
||
// ----04E4 = 1252 = Codepage for Windows:Multilingual
|
||
|
||
_snprintf_s(szGetName, 256, _TRUNCATE, "%sProductName", GetStringRes(IDS_VER_INFO_LANG));
|
||
|
||
// Set the title of the dialog:
|
||
bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
|
||
(LPSTR)szGetName,
|
||
(LPVOID)&lpVersion,
|
||
(UINT *)&uVersionLen);
|
||
|
||
// Notice order of version and string...
|
||
if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE)
|
||
{
|
||
_snprintf_s(szResult, 256, _TRUNCATE, "%s <20>̃o<CC83>[<5B>W<EFBFBD><57><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", lpVersion);
|
||
}
|
||
else
|
||
{
|
||
_snprintf_s(szResult, 256, _TRUNCATE, "About %s", lpVersion);
|
||
}
|
||
|
||
// -----------------------------------------------------
|
||
|
||
SetWindowText (hDlg, szResult);
|
||
|
||
// Walk through the dialog items that we want to replace:
|
||
for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++)
|
||
{
|
||
GetDlgItemText(hDlg, i, szResult, sizeof(szResult));
|
||
_snprintf_s(szGetName, 256, _TRUNCATE, "%s%s", GetStringRes(IDS_VER_INFO_LANG), szResult);
|
||
uVersionLen = 0;
|
||
lpVersion = NULL;
|
||
bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
|
||
(LPSTR)szGetName,
|
||
(LPVOID)&lpVersion,
|
||
(UINT *)&uVersionLen);
|
||
|
||
if ( bRetCode && uVersionLen && lpVersion)
|
||
{
|
||
// Replace dialog item text with version info
|
||
strncpy_s(szResult, 256, lpVersion, _TRUNCATE);
|
||
SetDlgItemText(hDlg, i, szResult);
|
||
}
|
||
else
|
||
{
|
||
dwResult = GetLastError();
|
||
|
||
_snprintf_s(szResult, 256, _TRUNCATE, GetStringRes(IDS_VERSION_ERROR), dwResult);
|
||
SetDlgItemText (hDlg, i, szResult);
|
||
}
|
||
SendMessage (GetDlgItem (hDlg, i), WM_SETFONT,
|
||
(UINT_PTR)((i==DLG_VERLAST)?hFinePrint:hfontDlg),
|
||
TRUE);
|
||
} // for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++)
|
||
|
||
|
||
GlobalUnlock(hMem);
|
||
GlobalFree(hMem);
|
||
|
||
}
|
||
else
|
||
{
|
||
// No version information available.
|
||
|
||
} // if (dwVerInfoSize)
|
||
|
||
SendMessage (GetDlgItem (hDlg, IDC_LABEL), WM_SETFONT,
|
||
(WPARAM)hfontDlg,(LPARAM)TRUE);
|
||
|
||
// We are using GetVersion rather then GetVersionEx
|
||
// because earlier versions of Windows NT and Win32s
|
||
// didn't include GetVersionEx:
|
||
dwVersion = GetVersion();
|
||
|
||
if (dwVersion < 0x80000000)
|
||
{
|
||
// Windows NT
|
||
_snprintf_s(szVersion, 40, _TRUNCATE, "Microsoft Windows NT %u.%u (Build: %u)",
|
||
(DWORD)(LOBYTE(LOWORD(dwVersion))),
|
||
(DWORD)(HIBYTE(LOWORD(dwVersion))),
|
||
(DWORD)(HIWORD(dwVersion)) );
|
||
}
|
||
else if (LOBYTE(LOWORD(dwVersion))<4)
|
||
{
|
||
// Win32s
|
||
_snprintf_s(szVersion, 40, _TRUNCATE, "Microsoft Win32s %u.%u (Build: %u)",
|
||
(DWORD)(LOBYTE(LOWORD(dwVersion))),
|
||
(DWORD)(HIBYTE(LOWORD(dwVersion))),
|
||
(DWORD)(HIWORD(dwVersion) & ~0x8000) );
|
||
}
|
||
else
|
||
{
|
||
// Windows 95
|
||
_snprintf_s(szVersion, 40, _TRUNCATE, "Microsoft Windows 95 %u.%u",
|
||
(DWORD)(LOBYTE(LOWORD(dwVersion))),
|
||
(DWORD)(HIBYTE(LOWORD(dwVersion))) );
|
||
}
|
||
|
||
SetWindowText (GetDlgItem(hDlg, IDC_OSVERSION), szVersion);
|
||
ShowWindow (hDlg, SW_SHOW);
|
||
return (TRUE);
|
||
|
||
case WM_COMMAND:
|
||
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
|
||
{
|
||
EndDialog(hDlg, TRUE);
|
||
DeleteObject (hfontDlg);
|
||
DeleteObject (hFinePrint);
|
||
return (TRUE);
|
||
}
|
||
break;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// FUNCTION: CenterWindow(HWND, HWND)
|
||
//
|
||
// PURPOSE: Centers one window over another.
|
||
//
|
||
// COMMENTS:
|
||
//
|
||
// In this function, we save the instance handle in a global variable and
|
||
// create and display the main program window.
|
||
//
|
||
// This functionwill center one window over another ensuring that
|
||
// the placement of the window is within the 'working area', meaning
|
||
// that it is both within the display limits of the screen, and not
|
||
// obscured by the tray or other framing elements of the desktop.
|
||
BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
|
||
{
|
||
RECT rChild, rParent, rWorkArea;
|
||
int wChild, hChild, wParent, hParent;
|
||
int xNew, yNew;
|
||
BOOL bResult;
|
||
|
||
// Get the Height and Width of the child window
|
||
GetWindowRect (hwndChild, &rChild);
|
||
wChild = rChild.right - rChild.left;
|
||
hChild = rChild.bottom - rChild.top;
|
||
|
||
// Get the Height and Width of the parent window
|
||
GetWindowRect (hwndParent, &rParent);
|
||
wParent = rParent.right - rParent.left;
|
||
hParent = rParent.bottom - rParent.top;
|
||
|
||
// Get the limits of the 'workarea'
|
||
bResult = SystemParametersInfo(
|
||
SPI_GETWORKAREA, // system parameter to query or set
|
||
sizeof(RECT),
|
||
&rWorkArea,
|
||
0);
|
||
if (!bResult)
|
||
{
|
||
rWorkArea.left = rWorkArea.top = 0;
|
||
rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
|
||
rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
|
||
}
|
||
|
||
// Calculate new X position, then adjust for workarea
|
||
xNew = rParent.left + ((wParent - wChild) /2);
|
||
if (xNew < rWorkArea.left)
|
||
{
|
||
xNew = rWorkArea.left;
|
||
}
|
||
else if ((xNew+wChild) > rWorkArea.right)
|
||
{
|
||
xNew = rWorkArea.right - wChild;
|
||
}
|
||
|
||
// Calculate new Y position, then adjust for workarea
|
||
yNew = rParent.top + ((hParent - hChild) /2);
|
||
if (yNew < rWorkArea.top)
|
||
{
|
||
yNew = rWorkArea.top;
|
||
}
|
||
else if ((yNew+hChild) > rWorkArea.bottom)
|
||
{
|
||
yNew = rWorkArea.bottom - hChild;
|
||
}
|
||
|
||
// Set it, and return
|
||
return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
||
}
|
||
|
||
|
||
//---------------------------------------------------------------------------
|
||
//
|
||
// FUNCTION: GetStringRes (int id INPUT ONLY)
|
||
//
|
||
// COMMENTS: Load the resource string with the ID given, and return a
|
||
// pointer to it. Notice that the buffer is common memory so
|
||
// the string must be used before this call is made a second time.
|
||
//
|
||
//---------------------------------------------------------------------------
|
||
|
||
LPTSTR GetStringRes (int id)
|
||
{
|
||
static TCHAR buffer[MAX_PATH];
|
||
|
||
buffer[0]=0;
|
||
LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
|
||
return buffer;
|
||
}
|
||
|