#include "stdafx.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif static int iGrind; HBITMAP hbmpGrind; const int BMP_WIDTH = 32; const int BMP_HEIGHT = 32; const int C_GRIND_IMAGES = 8 - 1; HDC hdcMem, hdcWnd; HBITMAP hbmpPreSelect; static int lPad; static int tPad; // This is the milliseconds we sleep before updating the grinder. const int GRIND_SLEEP = 500; static const char txtGrindClassName[] = "GrindClass"; LRESULT STDCALL GrindWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static DWORD STDCALL GetTextDimensions(HWND hwnd, PCSTR psz); static DWORD WINAPI GrindThread(LPVOID pv); static BOOL fStopGrinding; static HANDLE hthrd; static DWORD idThrd; static BOOL fRegistered; static PCSTR pszGrindTitle; static HANDLE hMainThrd; /*************************************************************************** FUNCTION: InitGrind PURPOSE: Initialize the grinder window PARAMETERS: void RETURNS: COMMENTS: MODIFICATION DATES: 11-Oct-1993 [ralphw] ***************************************************************************/ BOOL STDCALL InitGrind(PCSTR pszTitle) { if (iflags.fNoGrinder) return TRUE; pszGrindTitle = pszTitle; DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThrd, NULL, FALSE, DUPLICATE_SAME_ACCESS); HANDLE hthrd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &GrindThread, NULL, 0, &idThrd); if (hthrd) SetThreadPriority(hthrd, THREAD_PRIORITY_HIGHEST); return (BOOL) hthrd; } static DWORD WINAPI GrindThread(LPVOID pv) { /* * With small projects on a fast machine, we'll be done before * half a second is up, so before we bother creating our window, * we just sleep for awhile and then wake up and see if we really * need to do anything. */ Sleep(500); if (fStopGrinding) { ExitThread(0); hthrd = NULL; return 0; } hbmpGrind = LoadBitmap(hinstApp, MAKEINTRESOURCE(IDBMP_GRIND)); ASSERT(hbmpGrind); hdcMem = CreateCompatibleDC(NULL); if (!hdcMem) { ExitThread(0); hthrd = NULL; return 0; } if (!fRegistered) { WNDCLASS wc; memset(&wc, 0, sizeof(wc)); // Register Main window class wc.hInstance = hinstApp; wc.style = CS_BYTEALIGNWINDOW | CS_CLASSDC; wc.lpfnWndProc = GrindWndProc; wc.lpszClassName = txtGrindClassName; wc.hIcon = LoadIcon(hinstApp, MAKEINTRESOURCE(IDI_HCRTF)); wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); if (!RegisterClass(&wc)) { ExitThread(0); hthrd = NULL; return 0; } fRegistered = TRUE; } RECT rc; GetWindowRect(hwndParent ? hwndParent : GetDesktopWindow(), &rc); PCSTR pszWindowTitle = (pszGrindTitle ? pszGrindTitle : GetStringResource(IDS_GRINDER_TITLE)); int width = LOWORD(GetTextDimensions(NULL, pszWindowTitle)) + GetSystemMetrics(SM_CXSIZE) * 2; hwndGrind = CreateWindowEx(WS_EX_WINDOWEDGE, txtGrindClassName, pszWindowTitle, WS_SYSMENU | WS_CAPTION | WS_DLGFRAME, rc.left + RECT_WIDTH(rc) / 2 - width / 2, rc.top + RECT_HEIGHT(rc) / 2 - BMP_HEIGHT / 2, width + GetSystemMetrics(SM_CXDLGFRAME) * 2 + 2, BMP_HEIGHT + GetSystemMetrics(SM_CYDLGFRAME) * 2 + 6 + GetSystemMetrics(SM_CYMENU), hwndParent, NULL, hinstApp, NULL); lPad = width / 2 - GetSystemMetrics(SM_CXDLGFRAME) - 1; tPad = 3; if (!hwndGrind) { ExitThread(0); hthrd = NULL; return 0; } HWDLL_INIT hwInit; hwInit.cb = sizeof(HWDLL_INIT); hwInit.hinstApp = hinstApp; hwInit.pszErrorFile = "c:\\hcrtf.err"; hwInit.hwndWindow = hwndGrind; hwInit.CopyAssertInfo = NULL; hwInit.pszMsgBoxTitle = pgszTitleBuf; hwInit.version = 0; // at this point, we don't care about a version match InitializeHwDll(&hwInit); hbmpPreSelect = (HBITMAP) SelectObject(hdcMem, hbmpGrind); ASSERT(hbmpPreSelect); ShowWindow(hwndGrind, SW_NORMAL); if (hwndParent) SendMessage(hwndParent, WMP_HWND_GRINDER, (WPARAM) hwndGrind, 0); // This is a class DC, and therefore does not have to be released hdcWnd = GetDC(hwndGrind); while (!fStopGrinding) { BitBlt(hdcWnd, lPad, tPad, BMP_WIDTH, BMP_HEIGHT, hdcMem, iGrind * BMP_WIDTH, 0, SRCCOPY); if (++iGrind > C_GRIND_IMAGES) iGrind = 0; FlushMessageQueue(); // This isn't necesary under Windows 95 or NT 4.0 GdiFlush(); Sleep(GRIND_SLEEP); } if (hbmpPreSelect && hdcMem) SelectObject(hdcMem, hbmpPreSelect); if (hdcMem) { DeleteDC(hdcMem); hdcMem = NULL; } RemoveGdiObject(&hbmpGrind); if (hwndGrind) { DestroyWindow(hwndGrind); hwndGrind = NULL; FlushMessageQueue(); } // Tell our parent that they no longer have a valid window handle if (hwndParent) SendMessage(hwndParent, WMP_HWND_GRINDER, (WPARAM) (HWND) 0, 0); ExitThread(0); hthrd = NULL; return 0; } void STDCALL FlushMessageQueue(void) { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } LRESULT STDCALL GrindWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_KEYUP: if (wParam != VK_ESCAPE) return 0; // deliberately fall through case WM_CLOSE: case WMP_STOP_GRINDING: { CStr csz(IDS_TITLE); if (MessageBox(hwnd, GetStringResource(IDS_CONFIRM_ABORT), csz, MB_YESNO) == IDNO) return 0; } RemoveGrind(); if (hwndParent) PostMessage(hwndParent, WMP_STOP_COMPILING, 0, 0); fStopCompiling = TRUE; return 0; case WM_DESTROY: if (hbmpGrind) { /* * Set hwndGrind to NULL so that RemoveGrind() won't call * DestroyWindow(). */ hwndGrind = NULL; RemoveGrind(); SendStringToParent(GetStringResource(IDS_USER_ABORTING)); fStopCompiling = TRUE; } return 0; case WM_TCARD: fCntJump = (int) wParam; return 0; case WMP_NO_ACTIVATE: fNoActivation = TRUE; return 0; default: return DefWindowProc(hwnd, msg, wParam, lParam); } } /*************************************************************************** FUNCTION: GetTextDimensions PURPOSE: Get the width/height of the button PARAMETERS: hwnd psz RETURNS: COMMENTS: MODIFICATION DATES: 04-Feb-1993 [ralphw] ***************************************************************************/ static DWORD STDCALL GetTextDimensions(HWND hwnd, PCSTR psz) { HDC hdc = GetDC(hwnd); if (hdc == NULL) return 0L; SIZE size; GetTextExtentPoint(hdc, psz, strlen(psz), &size); ReleaseDC(hwnd, hdc); return MAKELONG(size.cx, size.cy); } void STDCALL RemoveGrind(void) { fStopGrinding = TRUE; // Tell our parent that they no longer have a valid window handle if (hwndParent) SendMessage(hwndParent, WMP_HWND_GRINDER, (WPARAM) (HWND) 0, 0); return; }