/***************************************************************************** * * * EWDEMO.C * * * * Copyright (C) Microsoft Corporation 1991. * * All Rights reserved. * * * ****************************************************************************** * * * Module Description: Implements an embedded window DLL that lists the * * current system printers. * * * *****************************************************************************/ #define NOMINMAX #include #include "dll.h" #include "dlldemo.h" #include #include #include #ifndef EXPORT #define EXPORT FAR PASCAL #endif #define PRIVATE static #define MAX_BUFFER 128 #define MAX_PRINTERS 10 #define MAX_PRINTERLINE 40 /***************************************************************************** * * * Global Variables * * * *****************************************************************************/ HANDLE ghModule; /* Handle to DLL */ char szPLClassName[] = "PrinterList"; /* printer list class name */ char rgchBuffer[MAX_BUFFER]; char rgrgchPrinters[MAX_PRINTERS][MAX_PRINTERLINE]; /***************************************************************************** * * * Prototypes * * * *****************************************************************************/ long EXPORT PrinterListProc (HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam); void NEAR PASCAL InitPrinterList( void ); /***************************************************************************** * * * Functions * * * *****************************************************************************/ /*************************************************************************** * - Name FInitEmbeddedWindow - * Purpose Called by LibMain during initialization of DLL. * * Arguments hModule Module handle for the library * * Returns * * +++ * * Notes * ***************************************************************************/ BOOL FInitEmbeddedWindow( HANDLE hModule ) { WNDCLASS wc; ghModule = hModule; wc.lpszClassName = szPLClassName; wc.style = CS_GLOBALCLASS; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = NULL; wc.lpszMenuName = NULL; wc.hbrBackground = COLOR_WINDOW + 1; wc.hInstance = hModule; wc.lpfnWndProc = PrinterListProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; if (!RegisterClass (&wc)) return FALSE; /* Initialization failed */ return TRUE; /* if we got here everything is ok! */ } /*************************************************************************** * - Name PrinterListProc - * Purpose Maintains a window with a list of the current system printers. * * Arguments hwnd This window's handle * wMsg The current message * wParam Message dependent * lParam Message dependent * * Returns Message dependent * * +++ * * Notes * ***************************************************************************/ long EXPORT PrinterListProc( HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam ) { PAINTSTRUCT ps; HANDLE gh; HBITMAP hbm; HBITMAP hbmDefault; HBRUSH hbrush; HDC hdc; HFONT hfont; int irgch; long lReturn; POINT pt; QCI qci; QRI qri; RECT rc; static char rgchHelpFile[_MAX_PATH]; static char rgchAuthorText[50]; LPSTR sz; TEXTMETRIC tm; switch (wMsg) { case WM_CREATE: qci = (QCI)((CREATESTRUCT FAR *)lParam)->lpCreateParams; /*------------------------------------------------------------*\ | Save the WM_CREATE information from WinHelp. \*------------------------------------------------------------*/ lstrcpy( rgchHelpFile, qci->szFileName ); if (lstrlen( qci->szAuthorData ) < 50) lstrcpy( rgchAuthorText, qci->szAuthorData ); /*------------------------------------------------------------*\ | Add a border to this window. \*------------------------------------------------------------*/ SetWindowLong( hwnd, GWL_STYLE, GetWindowLong( hwnd, GWL_STYLE ) | WS_BORDER ); /*------------------------------------------------------------*\ | Initialize the printer list. This could be updated more | dynamically, say on each WM_PAINT message. \*------------------------------------------------------------*/ InitPrinterList(); return 0L; case WM_PAINT: BeginPaint( hwnd, &ps ); GetTextMetrics( ps.hdc, &tm ); SetTextColor( ps.hdc, GetSysColor( COLOR_WINDOWTEXT ) ); SetBkColor( ps.hdc, GetSysColor( COLOR_WINDOW ) ); for (irgch = 0; irgch < MAX_PRINTERS && rgrgchPrinters[irgch][0]; irgch++) TextOut( ps.hdc, tm.tmMaxCharWidth/2, (tm.tmHeight + tm.tmExternalLeading)/2 + irgch*(tm.tmHeight + tm.tmExternalLeading), rgrgchPrinters[irgch], lstrlen( rgrgchPrinters[irgch] ) ); EndPaint( hwnd, &ps ); return 0L; case EWM_RENDER: /*-----------------------------------------------------------------*\ * Render message from WinHelp * wParam is the type of rendering requested. * lParam is a pointer to a RENDERINFO structure * Return the supported rendering. \*-----------------------------------------------------------------*/ switch( wParam ) { case CF_BITMAP: /*------------------------------------------------------------*\ | Prepare a bitmap image of the printer list. This will | appear in a similar manner as the layout, but we will need | to draw the border explicitly here, as well as making sure | the background is filled in correctly. We must use the | default colors for this hdc \*------------------------------------------------------------*/ qri = (QRI)lParam; hdc = CreateCompatibleDC( NULL ); if (hdc) { hfont = 0; /*------------------------------------------------------------*\ | Create a monochrome bitmap for the DC, sized for the screen. \*------------------------------------------------------------*/ SendMessage( hwnd, EWM_QUERYSIZE, hdc, (long)(LPPOINT)&pt ); rc.left = 0; rc.top = 0; rc.right = pt.x; rc.bottom = pt.y; hbm = CreateCompatibleBitmap( qri->hdc, pt.x, pt.y ); if (hbm) { hbmDefault = SelectObject( hdc, hbm ); /*------------------------------------------------------------*\ | Clear out the bitmap \*------------------------------------------------------------*/ hbrush = CreateSolidBrush( GetBkColor( hdc ) ); if (hbrush) { FillRect( hdc, &rc, hbrush ); DeleteObject( hbrush ); } Rectangle( hdc, rc.left, rc.top, rc.right, rc.bottom ); GetTextMetrics( hdc, &tm ); for (irgch = 0; irgch < MAX_PRINTERS && rgrgchPrinters[irgch][0]; irgch++) TextOut( hdc, tm.tmMaxCharWidth/2, (tm.tmHeight + tm.tmExternalLeading)/2 + irgch*(tm.tmHeight + tm.tmExternalLeading), rgrgchPrinters[irgch], lstrlen( rgrgchPrinters[irgch] ) ); /*----------------------------------------------------------*\ | At this point, hbm is the desired bitmap, sized for a | screen display. This will be stretched as needed for | the target display by WinHelp. \*----------------------------------------------------------*/ hbm = SelectObject( hdc, hbmDefault ); } else { /*------------------------------------------------------------*\ | Not enough memory. Cleanup and return NULL. \*------------------------------------------------------------*/ hbm = NULL; } DeleteDC( hdc ); } lReturn = (long)hbm; break; case CF_TEXT: /*------------------------------------------------------------*\ | List out the printers in a format suitable for the clipboard. | Since this list will be embedded in the text of the topic, | use blank lines for separators. \*------------------------------------------------------------*/ gh = GlobalAlloc( GMEM_MOVEABLE | GMEM_NOT_BANKED, sizeof(rgrgchPrinters) ); lReturn = (long)gh; if (gh) { sz = GlobalLock( gh ); lstrcpy( sz, "\r\n" ); for (irgch = 0; irgch < MAX_PRINTERS && rgrgchPrinters[irgch][0]; irgch++) { lstrcat( sz, rgrgchPrinters[irgch] ); lstrcat( sz, "\r\n" ); } GlobalUnlock( gh ); } break; default: lReturn = 0; } return lReturn; case EWM_QUERYSIZE: /*-----------------------------------------------------------------*\ * Size query message from WinHelp * wParam is the target hdc. * wLong is the address of the point to return size in. * Return non-zero to indicate that we did something. \*-----------------------------------------------------------------*/ hfont = SelectObject( (HDC)wParam, GetStockObject( SYSTEM_FONT ) ); GetTextMetrics( (HDC)wParam, &tm ); ((LPPOINT)lParam)->x = ((LPPOINT)lParam)->y = 0; for (irgch = 0; irgch < MAX_PRINTERS && rgrgchPrinters[irgch][0]; irgch++) { DWORD dwExt = GetTextExtent( (HDC)wParam, rgrgchPrinters[irgch], lstrlen( rgrgchPrinters[irgch] ) ); ((LPPOINT)lParam)->x = max( (WORD)((LPPOINT)lParam)->x, LOWORD(dwExt) ); ((LPPOINT)lParam)->y += HIWORD(dwExt); } ((LPPOINT)lParam)->x += tm.tmMaxCharWidth; ((LPPOINT)lParam)->y += tm.tmHeight + tm.tmExternalLeading; if (hfont) SelectObject( (HDC)wParam, hfont ); return 1; } return DefWindowProc (hwnd, wMsg, wParam, lParam); } /***************************************************************************** * * * Local Functions * * * *****************************************************************************/ /*************************************************************************** * - Name InitPrinterList - * Purpose Initializes the list of printers in the system * * Arguments none * * Returns nothing * * +++ * * Notes Uses the global variable rgrgchPrinters to store the system * printer list. * ***************************************************************************/ void NEAR PASCAL InitPrinterList( void ) { int irgch; char *pch; char *pchKey; char *pchTemp; /*------------------------------------------------------------*\ | These must be static, since we use near pointers into them, | and in a DLL DS!=SS. \*------------------------------------------------------------*/ static char rgchTemp[MAX_PRINTERLINE]; static char rgchDevice[MAX_PRINTERLINE]; GetProfileString( "windows", "device", "", rgchDevice, MAX_PRINTERLINE ); for (pch = rgchDevice; *pch != ',' && *pch != '\0'; pch++) ; *pch = '\0'; GetProfileString( "PrinterPorts", NULL, "", rgchBuffer, MAX_BUFFER ); for (pchKey = rgchBuffer, irgch = 0; *pchKey && irgch < MAX_PRINTERS; pchKey += lstrlen( pchKey ) + 1, irgch++) { lstrcpy( rgrgchPrinters[irgch], pchKey ); lstrcat( rgrgchPrinters[irgch], " on " ); GetProfileString( "PrinterPorts", pchKey, "", rgchTemp, MAX_PRINTERLINE ); for (pch = rgchTemp; *pch != ',' && *pch != '\0'; pch++) ; if (*pch == ',') { pchTemp = pch + 1; for (pch = pchTemp; *pch != ',' && *pch != '\0'; pch++) ; *pch = '\0'; lstrcat( rgrgchPrinters[irgch], pchTemp ); lstrcat( rgrgchPrinters[irgch], "," ); lstrcat( rgrgchPrinters[irgch], lstrcmp( pchKey, rgchDevice ) ? "inactive" : "active" ); } } }