A Simple Clipboard Viewer

Clipboard viewers don't have to be as sophisticated as CLIPBRD.EXE. A clipboard viewer can, for instance, display only one clipboard format. The CLIPVIEW program, shown in Figure 16-2, is a clipboard viewer that displays only the CF_TEXT format.

CLIPVIEW.MAK

#------------------------

# CLIPVIEW.MAK make file

#------------------------

clipview.exe : clipview.obj clipview.def

link clipview, /align:16, NUL, /nod slibcew libw, clipview

rc clipview.exe

clipview.obj : clipview.c

cl -c -Gsw -Ow -W2 -Zp clipview.c

CLIPVIEW.C

/*-----------------------------------------

CLIPVIEW.C -- Simple Clipboard Viewer

(c) Charles Petzold, 1990

-----------------------------------------*/

#include <windows.h>

long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,

LPSTR lpszCmdLine, int nCmdShow)

{

static char szAppName [] = "ClipView" ;

HWND hwnd ;

MSG msg ;

WNDCLASS wndclass ;

if (!hPrevInstance)

{

wndclass.style = CS_HREDRAW | CS_VREDRAW ;

wndclass.lpfnWndProc = WndProc ;

wndclass.cbClsExtra = 0 ;

wndclass.cbWndExtra = 0 ;

wndclass.hInstance = hInstance ;

wndclass.hIcon = NULL ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;

wndclass.lpszMenuName = NULL ;

wndclass.lpszClassName = szAppName ;

RegisterClass (&wndclass) ;

}

hwnd = CreateWindow (szAppName, "Simple Clipboard Viewer (Text Only)",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, nCmdShow) ;

UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

}

long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)

{

static HWND hwndNextViewer ;

HANDLE hGMem ;

HDC hdc ;

LPSTR lpGMem ;

PAINTSTRUCT ps ;

RECT rect ;

switch (message)

{

case WM_CREATE :

hwndNextViewer = SetClipboardViewer (hwnd) ;

return 0 ;

case WM_CHANGECBCHAIN :

if (wParam == hwndNextViewer)

hwndNextViewer = LOWORD (lParam) ;

else if (hwndNextViewer)

SendMessage (hwndNextViewer, message, wParam, lParam) ;

return 0 ;

case WM_DRAWCLIPBOARD :

if (hwndNextViewer)

SendMessage (hwndNextViewer, message, wParam, lParam) ;

InvalidateRect (hwnd, NULL, TRUE) ;

return 0 ;

case WM_PAINT :

hdc = BeginPaint (hwnd, &ps) ;

GetClientRect (hwnd, &rect) ;

OpenClipboard (hwnd) ;

if (hGMem = GetClipboardData (CF_TEXT))

{

lpGMem = GlobalLock (hGMem) ;

DrawText (hdc, lpGMem, -1, &rect, DT_EXPANDTABS) ;

GlobalUnlock (hGMem) ;

}

CloseClipboard () ;

EndPaint (hwnd, &ps) ;

return 0 ;

case WM_DESTROY :

ChangeClipboardChain (hwnd, hwndNextViewer) ;

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, message, wParam, lParam) ;

}

CLIPVIEW.DEF

;-------------------------------------

; CLIPVIEW.DEF module definition file

;-------------------------------------

NAME CLIPVIEW

DESCRIPTION 'Simple Clipboard Viewer (c) Charles Petzold, 1990'

EXETYPE WINDOWS

STUB 'WINSTUB.EXE'

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE MULTIPLE

HEAPSIZE 1024

STACKSIZE 8192

EXPORTS WndProc

CLIPVIEW processes WM_CREATE, WM_CHANGECBCHAIN, WM_DRAWCLIPBOARD, and WM_DESTROY messages as discussed above. The WM_PAINT message simply opens the clipboard and uses GetClipboardData with a format of CF_TEXT. If the function returns a global memory handle, CLIPVIEW locks it and uses DrawText to display the text in its client area.

A clipboard viewer that handles data formats beyond the five standard formats (as CLIPBRD.EXE does) has additional work to do, such as displaying the names of all the formats currently in the clipboard. You can do this by calling EnumClipboardFormats and obtaining the names of the nonstandard formats from GetClipboardFormatName. A clipboard viewer that uses the CF_OWNERDISPLAY format must send these four messages to the clipboard to display the data:

WM_PAINTCLIPBOARD WM_VSCROLLCLIPBOARD
WM_SIZECLIPBOARD WM_HSCROLLCLIPBOARD

If you want to write such a clipboard viewer, you have to obtain the window handle of the clipboard owner using GetClipboardOwner and send that window these messages when you need to update the clipboard viewer's client area.