|
|
1.1 root 1: /*
2: * CLIPVIEW.C -- Clipboard Viewing application
3: * Created by Microsoft, IBM Corporation, 1990
4: *
5: * DISCLAIMER OF WARRANTIES. The following [enclosed] code is
6: * sample code created by Microsoft Corporation and/or IBM
7: * Corporation. This sample code is not part of any standard
8: * Microsoft or IBM product and is provided to you solely for
9: * the purpose of assisting you in the development of your
10: * applications. The code is provided "AS IS", without
11: * warranty of any kind. Neither Microsoft nor IBM shall be
12: * liable for any damages arising out of your use of the sample
13: * code, even if they have been advised of the possibility of
14: * such damages.
15: *
16: * This program registers itself as the clipboard viewer, if no clipboard
17: * viewer exists. Then, it intercepts WM_DRAWCLIPBOARD messages.
18: *
19: * This file contains the routines which handle the client/frame windows,
20: * the dialog routines, and the clipboard rendering code.
21: */
22:
23:
24: /* Currently MLE control are not implemented in OS/2 2.0 therefore
25: * all references to MLE have been #defined out of the picture
26: * as soon as they become implemented uncomment MLE_OK and everything
27: * should work as originally intended
28: */
29:
30:
31: /*****************
32:
33:
34: #define MLE_OK
35:
36:
37: ******************/
38:
39:
40:
41:
42: #define INCL_GPIBITMAPS
43: #define INCL_GPIMETAFILES
44: #define INCL_WINATOM
45: #define INCL_WINCLIPBOARD
46: #define INCL_WINFRAMEMGR
47: #define INCL_WINLISTBOXES
48: #define INCL_WINMENUS
49: #define INCL_WINMLE
50: #define INCL_WINSCROLLBARS
51: #define INCL_WINSYS
52: #define INCL_WINWINDOWMGR
53: #define INCL_GPILCIDS
54: #include <os2.h>
55: #include <string.h>
56: #include <ctype.h>
57: #include "clipview.h"
58: /*
59: * Globals
60: */
61: BITMAPINFOHEADER vbmp; // Dimensions of current BITMAP
62: BOOL vfUpdate = FALSE; // Are we updating the clipboard?
63: BOOL vfViewBitmap = FALSE; // Are we currently viewing a...?
64: BOOL vfViewText = FALSE; // Are we currently viewing text
65: HAB vhab; // Anchor block
66: HDC vhdcMemory; // A memory DC for BitBlt-ing images
67: HDC vhdcWindow = NULL; // Client window DC
68: HMQ vhmqClip; // Message queue
69: HPS vhpsMemory; // A PS associated with vhdcMemory
70: HWND vhwndClient; // Main client area
71: HWND vhwndClipFrame = NULL; // Main frame window
72: HWND vhwndHSB = NULL; // Horizontal scroll bar
73:
74:
75:
76: HWND vhwndMLE = NULL; // Handle to the MLE
77:
78:
79:
80: HWND vhwndTitlebar = NULL; // Title-bar handle
81: HWND vhwndVSB = NULL; // Vertical scroll bar
82: SHORT vcMaxHSB; // Maximum scroll range for HSB
83: SHORT vcMaxVSB; // ...and for the VSB
84: SHORT vcUpdate = -1; // Counter for scroll bar updating
85: USHORT vausFormats[MAXFORMATS]; // All available formats
86: USHORT vcFmts; // How many formats?
87: USHORT vusFormat; // What is the current format?
88: USHORT vfsFmtInfo; // Clipboard Format Information
89: /*
90: Macros
91: */
92: #define LOADSTRING(id, sz) WinLoadString(vhab, NULL, id, MAXLEN, sz)
93: #define MESSAGE(sz) WinMessageBox(HWND_DESKTOP, vhwndClient, sz, NULL, NULL, \
94: MB_OK | MB_ICONASTERISK | MB_SYSTEMMODAL);
95: /*
96: * Main routine...initializes window and message queue
97: */
98: int cdecl main( ) {
99: QMSG qmsg; /* Message queue */
100: ULONG ctldata; /* FCF_ flags */
101: BOOL fViewer; /* Does a viewer already exist? */
102: UCHAR szAlready[MAXLEN]; /* Already extant... message */
103: UCHAR szClassName[MAXLEN]; /* New class name */
104: /*
105: Start up our PM application
106: */
107: vhab = WinInitialize(NULL);
108: vhmqClip = WinCreateMsgQueue(vhab, 0);
109: /*
110: We create the client window first to try to avoid
111: synchronization problems.
112: */
113: LOADSTRING(IDS_CLIPCLASS, szClassName);
114: if (!WinRegisterClass( vhab, (PCH)szClassName, (PFNWP)ClipWndProc,
115: CS_SIZEREDRAW, 0))
116: return( 0 );
117: /*
118: Create the window (hidden)
119: */
120: ctldata = (FCF_STANDARD | FCF_HORZSCROLL | FCF_VERTSCROLL)
121: & ~(FCF_ACCELTABLE);
122:
123: vhwndClipFrame = WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE, &ctldata,
124: szClassName, "",
125: WS_VISIBLE, NULL, ID_RESOURCE,
126: (PHWND) &vhwndClient );
127: /*
128: If there is no other clipboard viewer...
129: */
130: if (fViewer = !WinQueryClipbrdViewer(vhab, FALSE)) {
131: /*
132: ...we'll be the viewer. Show the clipboard window.
133: */
134: WinSetClipbrdViewer(vhab, vhwndClient);
135: /*
136: Poll messages from event queue
137: */
138: while( WinGetMsg( vhab, (PQMSG)&qmsg, (HWND)NULL, 0, 0 ) )
139: WinDispatchMsg( vhab, (PQMSG)&qmsg );
140: /*
141: Stop being the clipboard viewer.
142: */
143:
144:
145: #ifdef MLE_OK
146:
147: if (vhwndMLE)
148: WinDestroyWindow(vhwndMLE);
149:
150: #endif
151:
152:
153: WinSetClipbrdViewer(vhab, NULL);
154:
155: } else {
156: /*
157: ...otherwise, notify the user, then terminate.
158: */
159: LOADSTRING(IDS_ALREADY, szAlready);
160: MESSAGE(szAlready);
161: }
162: /*
163: Clean up
164: */
165: WinDestroyWindow( vhwndClipFrame );
166: WinDestroyMsgQueue( vhmqClip );
167: WinTerminate( vhab );
168:
169: return !fViewer;
170: }
171:
172: MRESULT EXPENTRY ClipWndProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2) {
173: /*
174:
175: * This routine processes WM_COMMAND, WM_CREATE, WM_DRAWCLIPBOARD, WM_PAINT.
176: * Everything else is passed to the Default Window Procedure.
177: */
178: HPS hpsWindow;
179: RECTL rcl;
180: SWP swp;
181: SIZEL sizl;
182: UCHAR szMessage[MAXLEN];
183:
184: switch (msg) {
185:
186: case WM_CREATE:
187: /*
188: Create a memory DC/PS to BitBlt BITMAPs around.
189: */
190: sizl.cx = sizl.cy = 0L;
191: vhdcMemory = DevOpenDC(vhab, OD_MEMORY, "*", 0L, NULL, NULL);
192: vhpsMemory = GpiCreatePS(vhab, vhdcMemory, &sizl,
193: GPIA_ASSOC | GPIF_DEFAULT | GPIT_MICRO | PU_PELS);
194: break;
195:
196: case WM_COMMAND:
197: switch ((USHORT) SHORT1FROMMP (mp1)) {
198: /*
199: About... dialog box
200: */
201: case IDM_ABOUT:
202: WinDlgBox(HWND_DESKTOP, hwnd, AboutDlgProc,
203: NULL, IDD_ABOUT, NULL);
204: return 0;
205: /*
206: Render... dialog box
207: */
208: case IDM_RENDER:
209: WinDlgBox(HWND_DESKTOP, hwnd, RenderDlgProc,
210: NULL, IDD_RENDER, NULL);
211: return 0;
212: /*
213: Save... dialog box
214: */
215: case IDM_SAVE:
216: if (!SaveClipboard(hwnd, vusFormat)) {
217: LOADSTRING(IDS_NOTSAVED, szMessage);
218: MESSAGE(szMessage);
219: }
220: return 0;
221:
222: default: break;
223: }
224: break;
225:
226: case WM_ERASEBACKGROUND:
227: return MRFROMSHORT (TRUE) ;
228: break;
229:
230: case WM_PAINT:
231: /* Open the presentation space */
232: hpsWindow = WinBeginPaint(hwnd, NULL, &rcl);
233:
234: /* Fill in the background */
235: WinFillRect(hpsWindow, &rcl, CLR_BACKGROUND);
236:
237: /* Paint in the clipboard */
238: UpdateScreen(hwnd, vusFormat);
239:
240: /* Finish painting */
241: WinEndPaint(hpsWindow);
242: break;
243:
244: case WM_DRAWCLIPBOARD:
245: /* Update the clipboard contents */
246: GetAllFormats();
247: vfUpdate = TRUE;
248: WinPostMsg(hwnd, WM_PAINT, 0L, 0L);
249: break;
250:
251: case WM_HSCROLL:
252: if (vfViewBitmap) {
253: /*
254: Handle the appropriate scrolling messages
255: */
256: DoScrolling(hwnd, TRUE, HIUSHORT(mp2));
257: }
258: else if ( vfViewText ) {
259: DoScrolling(hwnd, TRUE, HIUSHORT(mp2));
260: } else
261: /*
262: If an ownerdraw format, let the owner handle it.
263: */
264: SendOwnerMsg(WM_HSCROLLCLIPBOARD, (MPARAM) hwnd, mp2);
265: break;
266:
267: case WM_VSCROLL:
268: if (vfViewBitmap) {
269: /*
270: Handle the appropriate scrolling messages
271: */
272: DoScrolling(hwnd, FALSE, HIUSHORT(mp2));
273: }
274: else if ( vfViewText ) {
275: DoScrolling(hwnd, FALSE, HIUSHORT(mp2));
276: } else
277: /*
278: If an ownerdraw format, let the owner handle it.
279: */
280: SendOwnerMsg(WM_VSCROLLCLIPBOARD, (MPARAM) hwnd, mp2);
281: break;
282:
283: case WM_SIZE:
284:
285:
286: /*
287: If the MLE is processing a text selector,
288: tell it to resize itself. If we have
289: owner-draw data, tell the clipboard owner.
290: If we have a BITMAP, readjust the scroll
291: bar ranges.
292: */
293:
294:
295: if (vhwndMLE) {
296: WinQueryWindowPos(vhwndMLE, &swp);
297: swp.cx = SHORT1FROMMP(mp2);
298: swp.cy = SHORT2FROMMP(mp2);
299: WinSetMultWindowPos(vhab, &swp, 1);
300: } else if (vfViewBitmap) {
301: WinQueryWindowPos(hwnd, &swp);
302: if ((vcMaxHSB = vbmp.cx - swp.cx) < 0)
303: vcMaxHSB = 0;
304: if ((vcMaxVSB = vbmp.cy - swp.cy) < 0)
305: vcMaxVSB = 0;
306: WinSendMsg(vhwndHSB, SBM_SETSCROLLBAR,
307: 0L, MPFROM2SHORT(0, vcMaxHSB));
308: WinSendMsg(vhwndVSB, SBM_SETSCROLLBAR,
309: MPFROMSHORT(vcMaxVSB),
310: MPFROM2SHORT(0, vcMaxVSB));
311: } else {
312: rcl.xLeft = rcl.yBottom = 0L;
313: rcl.xLeft = (LONG) SHORT1FROMMP(mp2) - 1;
314: rcl.yTop = (LONG) SHORT2FROMMP(mp2) - 1;
315: SendOwnerMsg(WM_SIZECLIPBOARD, (MPARAM) hwnd, &rcl);
316: }
317:
318:
319: break;
320:
321: default:
322: return WinDefWindowProc(hwnd, msg, mp1, mp2);
323: break;
324: }
325: return 0L;
326: }
327:
328: MRESULT EXPENTRY RenderDlgProc(HWND hwndDlg, USHORT msg, MPARAM mp1, MPARAM mp2)
329: {
330: /*
331: Render... dialog procedure
332: */
333: HWND hwndListbox; /* Listbox of possible formats */
334: UCHAR szFmtName[MAXLEN]; /* Format name */
335: UCHAR szMessage[MAXLEN];
336: USHORT i;
337: USHORT usFormat; /* Format to render */
338: MRESULT mrItem; /* Which listbox item selected? */
339:
340: switch(msg) {
341:
342: case WM_INITDLG:
343: /*
344: Put all the possible formats into the listbox, and
345: select the first item by default.
346: */
347: hwndListbox = WinWindowFromID(hwndDlg, IDL_RENDER);
348: WinSendMsg(hwndListbox, LM_DELETEALL, 0L, 0L);
349: for (i = 0; i < vcFmts; i++) {
350: GetFormatName(vausFormats[i], szFmtName);
351: WinSendMsg(hwndListbox, LM_INSERTITEM,
352: MPFROMSHORT(LIT_END), MPFROMP((PVOID) szFmtName));
353: }
354: WinSendMsg(hwndListbox, LM_SELECTITEM, 0L, MPFROMSHORT(TRUE));
355: break;
356:
357: case WM_CONTROL:
358: /*
359: If the user makes a selection, quit!
360: */
361: if ((SHORT1FROMMP(mp1) == IDL_RENDER)
362: && (SHORT2FROMMP(mp1) == LN_ENTER))
363: WinPostMsg(hwndDlg, WM_COMMAND, MPFROMSHORT(DID_OK), 0L);
364: break;
365:
366: case WM_COMMAND:
367: switch( (USHORT) SHORT1FROMMP (mp1) ) {
368: case DID_OK:
369: /*
370: Since the user chose a selection, try to render it.
371: */
372: hwndListbox = WinWindowFromID(hwndDlg, IDL_RENDER);
373: mrItem = WinSendMsg(hwndListbox, LM_QUERYSELECTION, 0L, 0L);
374: if (mrItem != MPFROMSHORT (LIT_NONE) ) {
375: usFormat = vausFormats[(USHORT) mrItem];
376: if (usFormat != vusFormat) {
377: /*
378: If the clipboard format is not rendered,
379: tell the user.
380: */
381: vfUpdate = TRUE;
382: if (!UpdateScreen(vhwndClient, usFormat)) {
383: LOADSTRING(IDS_NODISPLAY, szMessage);
384: MESSAGE(szMessage);
385: }
386: }
387: }
388:
389: /* fall through */
390:
391: case DID_CANCEL:
392: WinDismissDlg(hwndDlg, TRUE);
393:
394: default: break;
395: }
396: default: return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
397: }
398: return FALSE;
399: }
400:
401: MRESULT EXPENTRY AboutDlgProc(HWND hwndDlg, USHORT msg, MPARAM mp1, MPARAM mp2)
402: {
403: /*
404: About... dialog procedure
405: */
406: switch(msg) {
407: case WM_COMMAND:
408: switch( (USHORT) SHORT1FROMMP (mp1) ) {
409: case DID_OK: WinDismissDlg(hwndDlg, TRUE);
410: default: break;
411: }
412: default: return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
413: }
414: return FALSE;
415: }
416:
417:
418:
419:
420: #ifdef MLE_OK
421:
422: VOID ReadSelector(HWND hwndMLE, PSZ pszText) {
423: /*
424: Compute the length of the text selector, in bytes.
425: Allocate space, and copy the text selector into an MLE.
426: */
427: IPT ipt = 0L ;
428: ULONG ulcch = 0;
429: PSZ pszCounter;
430:
431: pszCounter = pszText;
432: while (*pszCounter++) ulcch++;
433: WinSendMsg(hwndMLE, MLM_FORMAT, MPFROMSHORT(MLFIE_CFTEXT), 0L);
434: WinSendMsg(hwndMLE, MLM_SETIMPORTEXPORT, pszText, (MPARAM) ulcch);
435: WinSendMsg(hwndMLE, MLM_IMPORT, (MPARAM) &ipt, (MPARAM) ulcch);
436: }
437:
438: #endif
439:
440:
441:
442: VOID FixFrame(VOID) {
443: /*
444: This routine tells the frame to update the scroll bars.
445:
446: First, make it so that the scroll bars cannot update themselves.
447: Let the frame update the controls. Then, re-enable the scroll bars.
448: */
449: if (!(vcUpdate--)) {
450: WinEnableWindowUpdate(vhwndHSB, FALSE);
451: WinEnableWindowUpdate(vhwndVSB, FALSE);
452: }
453:
454:
455: WinSendMsg(vhwndClipFrame, WM_UPDATEFRAME, MPFROMLONG(FCF_HORZSCROLL), 0L);
456: WinSendMsg(vhwndClipFrame, WM_UPDATEFRAME, MPFROMLONG(FCF_VERTSCROLL), 0L);
457:
458:
459: if (!(++vcUpdate)) {
460: WinEnableWindowUpdate(vhwndHSB, TRUE);
461: WinEnableWindowUpdate(vhwndVSB, TRUE);
462: }
463: }
464:
465: VOID NeedScrollBars(BOOL fNeed) {
466: /*
467: This routine hides changes the scroll bar state to correspond with
468: fNeed, showing or hiding them as necessary.
469: */
470: static BOOL fNeeded = TRUE; /* The last scroll bar state */
471:
472: /*
473: Get the scroll bar handles, if we haven't already.
474: */
475: if (!vhwndHSB) {
476: vhwndHSB = WinWindowFromID(vhwndClipFrame, FID_HORZSCROLL);
477: vhwndVSB = WinWindowFromID(vhwndClipFrame, FID_VERTSCROLL);
478: }
479: /*
480: Case 1: We need scroll bars, so enable them.
481: */
482: if (fNeed) {
483: if (!fNeeded) {
484: WinSetParent(vhwndHSB, vhwndClipFrame, TRUE);
485: WinSetParent(vhwndVSB, vhwndClipFrame, TRUE);
486: FixFrame();
487: }
488: /*
489: Case 2: We don't need scroll bars, so hide them.
490: */
491: } else {
492: if (fNeeded) {
493: WinSetParent(vhwndHSB, HWND_OBJECT, TRUE);
494: WinSetParent(vhwndVSB, HWND_OBJECT, TRUE);
495: FixFrame();
496: }
497: }
498: /*
499: Save state for next invocation
500: */
501: fNeeded = fNeed;
502: }
503:
504: /*
505: RenderFormat()
506:
507: Input: Clipboard format to render, and handle to client area
508: Side effects: Renders the image in the client area
509: */
510: BOOL RenderFormat(HWND hwnd, USHORT usFormat) {
511: BOOL fRendered = TRUE;
512: HMF hmfCopy;
513: HPS hpsWindow;
514: LONG alOptions[8];
515: RECTL rclWindow;
516: SIZEL sizl;
517: SWP swpWindow;
518: ULONG hItem;
519: POINTL aptl[3];
520:
521:
522: #ifndef MLE_OK
523:
524:
525: HPS hps ;
526: RECTL rcl ;
527: POINTL ptl ;
528: FONTMETRICS fm ;
529: PSZ pszText ;
530: SHORT cxCaps, cyChar, cyDesc, line ;
531:
532: #endif
533:
534: /*
535: Open the clipboard
536: */
537: if (!WinOpenClipbrd(vhab))
538: return FALSE;
539: /*
540: Open up the window DC and PS
541: */
542: if (!vhdcWindow)
543: vhdcWindow = WinOpenWindowDC(hwnd);
544:
545: sizl.cx = sizl.cy = 0L;
546: hpsWindow = GpiCreatePS(vhab, vhdcWindow, &sizl, GPIA_ASSOC | PU_ARBITRARY);
547: /*
548: Enable the scroll bars, if necessary. This affects the size
549: of the client area.
550: */
551: if (vfUpdate)
552: NeedScrollBars( (vfViewBitmap =
553: (usFormat == CF_BITMAP) || (usFormat == CF_DSPBITMAP) ||
554:
555: /* The following line should be deleted when MLE are implemented */
556:
557: (usFormat == CF_DSPTEXT) || (usFormat == CF_TEXT) ) );
558:
559: WinQueryWindowRect(hwnd, &rclWindow);
560: /*
561: Get the clipboard data
562: */
563: WinQueryClipbrdFmtInfo(vhab, usFormat, &vfsFmtInfo);
564: if (!(hItem = WinQueryClipbrdData(vhab, usFormat))) {
565: fRendered = FALSE;
566: } else {
567: /*
568: Display the new format, as appropriate.
569: */
570: switch (usFormat) {
571: case CF_TEXT:
572: case CF_DSPTEXT:
573: if (vfUpdate) {
574:
575:
576: #ifdef MLE_OK
577:
578:
579: Create a new MLE and read the text into it.
580:
581: vhwndMLE = WinCreateWindow(hwnd, WC_MLE, "",
582: WS_VISIBLE | MLS_READONLY | MLS_HSCROLL | MLS_VSCROLL,
583: 0, 0,
584: (SHORT) rclWindow.xRight, (SHORT) rclWindow.yTop,
585: hwnd, HWND_TOP, 0, NULL, NULL);
586:
587: ReadSelector(vhwndMLE, (PSZ) hItem ) ;
588:
589: #else
590: vfViewText = TRUE ;
591: hps = WinGetPS ( hwnd ) ;
592: WinQueryWindowRect ( hwnd, &rcl ) ;
593: GpiQueryFontMetrics ( hps, (LONG) sizeof (fm), &fm ) ;
594: cxCaps = (SHORT) fm.lEmInc ;
595: cyChar = (SHORT) fm.lMaxBaselineExt ;
596: cyDesc = (SHORT) fm.lMaxDescender ;
597: line = 0 ;
598:
599: while ( *(PSZ) hItem ) {
600: pszText = (PSZ) hItem ;
601: ptl.x = cxCaps ;
602: ptl.y = rcl.yTop - cyChar * (line + 1) + cyDesc ;
603:
604: while ( isprint ( *(PSZ) hItem) )
605: hItem++ ;
606:
607: if ( *(PSZ) hItem )
608: GpiCharStringAt ( hps,
609: &ptl,
610: hItem - (ULONG) pszText,
611: pszText ) ;
612:
613: while ( isspace ( *(PSZ) hItem ) )
614: hItem++ ;
615:
616: line += 1 ;
617: }
618:
619: hItem = (ULONG) pszText ;
620: while ( isprint ( *(PSZ) hItem ) )
621: hItem++ ;
622:
623: GpiCharStringAt ( hps, &ptl, hItem - (ULONG) pszText, pszText ) ;
624:
625: WinReleasePS ( hps ) ;
626: #endif
627:
628:
629: }
630: break;
631:
632: case CF_BITMAP:
633: case CF_DSPBITMAP:
634: if (vfUpdate) {
635: /*
636: Get the BITMAP dimensions, for scroll bar processing
637: */
638: if (GpiQueryBitmapParameters((HBITMAP) hItem, &vbmp)
639: != GPI_OK) {
640: return FALSE;
641: }
642: /*
643: Set the scroll bar ranges from 0 to vbmp.max - client.max
644: */
645: WinQueryWindowPos(hwnd, &swpWindow);
646:
647: if ((vcMaxHSB = vbmp.cx - swpWindow.cx) < 0)
648: vcMaxHSB = 0;
649: if ((vcMaxVSB = vbmp.cy - swpWindow.cy) < 0)
650: vcMaxVSB = 0;
651: WinSendMsg(vhwndHSB, SBM_SETSCROLLBAR,
652: 0L, MPFROM2SHORT(0, vcMaxHSB));
653: WinSendMsg(vhwndVSB, SBM_SETSCROLLBAR,
654: MPFROMSHORT(vcMaxVSB),
655: MPFROM2SHORT(0, vcMaxVSB));
656: }
657: /*
658: Draw the BITMAP, based on the scroll bar settings.
659: */
660: GpiSetBitmap(vhpsMemory, (HBITMAP) hItem);
661:
662: aptl[0].x = rclWindow.xLeft; /* Target bottom left */
663: aptl[0].y = rclWindow.yBottom;
664: aptl[1].x = rclWindow.xRight; /* Target top right */
665: aptl[1].y = rclWindow.yTop;
666: /* Source bottom left */
667: aptl[2].x = (LONG) WinSendMsg(vhwndHSB, SBM_QUERYPOS, 0L, 0L);
668: aptl[2].y = vcMaxVSB
669: - (LONG) WinSendMsg(vhwndVSB, SBM_QUERYPOS, 0L, 0L);
670:
671: GpiBitBlt(hpsWindow, vhpsMemory, 3L, aptl, ROP_SRCCOPY, 0L);
672: GpiSetBitmap(vhpsMemory, NULL);
673: break;
674:
675: case CF_METAFILE:
676: case CF_DSPMETAFILE:
677: /*
678: Set up the alOptions for displaying the metafile, and
679: let the system do the rest of the work.
680: */
681: alOptions[PMF_SEGBASE] = 0L;
682: alOptions[PMF_LOADTYPE] = LT_DEFAULT;
683: alOptions[PMF_RESOLVE] = 0L;
684: alOptions[PMF_LCIDS] = LC_LOADDISC;
685: alOptions[PMF_RESET] = RES_DEFAULT;
686: alOptions[PMF_SUPPRESS] = SUP_DEFAULT;
687: alOptions[PMF_COLORTABLES] = CTAB_NOMODIFY;
688: alOptions[PMF_COLORREALIZABLE] = CREA_DEFAULT;
689: hmfCopy = GpiCopyMetaFile((HMF) hItem);
690: GpiPlayMetaFile(hpsWindow, hmfCopy, 8L, alOptions, 0L, 0L, NULL);
691: break;
692:
693: case CF_EMPTY:
694: /*
695: Don't do anything.
696: */
697: break;
698:
699: default:
700: /*
701: If it's an owner-draw format that we can display...
702: ...try to get the owner to paint the clipboard.
703: (return if we were successful or not)
704: */
705: fRendered = SendOwnerMsg(WM_PAINTCLIPBOARD, MPFROMHWND(hwnd), 0L);
706: break;
707: }
708: }
709: /*
710: Tell everybody that the client area is valid now
711: */
712: WinValidateRect(hwnd, (PRECTL) NULL, FALSE);
713: /*
714: Clean up
715: */
716: GpiAssociate(hpsWindow, NULL);
717: GpiDestroyPS(hpsWindow);
718: WinCloseClipbrd(vhab);
719: return fRendered;
720: }
721:
722: BOOL UpdateScreen(HWND hwnd, USHORT usFormat) {
723: /*
724: Render the format, change the title bar.
725: The title bar will look like: "<appname> (<format>)"
726: */
727: BOOL fRendered = TRUE;
728: HPS hpsWindow;
729: RECTL rcl;
730: UCHAR szFormat[MAXLEN];
731: UCHAR szTitle[MAXTITLELEN];
732:
733: if (vfUpdate) {
734:
735:
736: #ifdef MLE_OK
737:
738: /* If the MLE exists, destroy it */
739: if (vhwndMLE) {
740: WinDestroyWindow(vhwndMLE);
741: vhwndMLE = NULL;
742: }
743: #endif
744:
745: /* Clear the client area */
746: WinQueryWindowRect(hwnd, &rcl);
747: WinInvalidateRect(hwnd, &rcl, FALSE);
748: hpsWindow = WinBeginPaint(hwnd, NULL, NULL);
749: WinFillRect(hpsWindow, &rcl, CLR_BACKGROUND);
750: WinEndPaint(hpsWindow);
751: }
752: if (usFormat) // Check that usFormat != CF_EMPTY
753: fRendered = RenderFormat(hwnd, usFormat);
754: /*
755: Set the title bar appropriately
756: */
757: if (!vhwndTitlebar && vhwndClipFrame)
758: vhwndTitlebar = WinWindowFromID(vhwndClipFrame, FID_TITLEBAR);
759:
760: if (vhwndTitlebar) {
761: GetFormatName(usFormat, szFormat);
762: LOADSTRING(IDS_APPNAME, szTitle);
763: strcat(szTitle, "("); strcat(szTitle, szFormat); strcat(szTitle, ")");
764: WinSetWindowText(vhwndTitlebar, szTitle);
765: }
766: /*
767: Save the rendered format.
768: */
769: vusFormat = usFormat;
770: return fRendered;
771: }
772:
773: VOID GetAllFormats(VOID) {
774: USHORT usFormat; // Temporary used when enumerating
775: /*
776: Put ourselves into a clean state
777: */
778: usFormat = vcFmts = 0;
779: /*
780: Cycle through the available clipboard formats
781: */
782: while (usFormat = WinEnumClipbrdFmts(vhab, usFormat)) {
783: vausFormats[vcFmts++] = usFormat;
784: }
785: /*
786: Set the current clipboard format to the first one, if possible
787: (in preparation for the WM_PAINT which will follow).
788: */
789: vusFormat = (vcFmts ? vausFormats[0] : CF_EMPTY);
790: }
791:
792: VOID GetFormatName(USHORT usFormat, UCHAR szFmtName[]) {
793: /*
794: GetFormatName()
795:
796: This routine returns a format name in szFmtName which corresponds
797: to the format usFormat. Basically, either we know the format, or
798: we get the name from the system atom table. If we can't find it,
799: we set it to CF_UNKNOWN.
800: */
801: switch (usFormat) {
802: /*
803: If we know the format, we can read it from the string table.
804: */
805: case CF_EMPTY:
806: case CF_TEXT:
807: case CF_DSPTEXT:
808: case CF_BITMAP:
809: case CF_DSPBITMAP:
810: case CF_METAFILE:
811: case CF_DSPMETAFILE:
812: LOADSTRING(usFormat, szFmtName);
813: break;
814:
815: default:
816: /*
817: Get the format name from the system atom table.
818: If not found, tag it as an unknown format.
819: */
820: if (!WinQueryAtomName(WinQuerySystemAtomTable(),
821: usFormat, szFmtName, MAXLEN))
822:
823: LOADSTRING(CF_UNKNOWN, szFmtName);
824:
825: break;
826: }
827: }
828:
829: BOOL SendOwnerMsg(USHORT msg, MPARAM mp1, MPARAM mp2) {
830: BOOL rc;
831: HWND hwndOwner;
832: /*
833: If we are an OWNERDISPLAY format,
834: lock the owner window, tell it to perform the operation, return
835: */
836: if ( rc = ( (vfsFmtInfo & CFI_OWNERDISPLAY)
837: && (hwndOwner = WinQueryClipbrdOwner(vhab, TRUE)) ) ) {
838:
839: WinSendMsg(hwndOwner, msg, mp1, mp2);
840: WinLockWindow(hwndOwner, FALSE);
841: }
842: return rc;
843: }
844:
845: BOOL DoScrolling(HWND hwnd, BOOL fHorz, USHORT sbCmd) {
846: /*
847: This routine depends on the fact that the thumb cannot be set past the
848: range of the scroll bar. Since this is handled in the system SBM_SETPOS
849: code already, we need not worry about it.
850:
851: We return TRUE if the scroll bar message is processed.
852: */
853: HWND hwndSB; /* Scroll bar handle */
854: USHORT cpels; /* Page length/width for PAGExxxx commands */
855: SWP swp; /* Dimensions of the client area */
856: USHORT usOld; /* The current scroll bar position */
857: USHORT usNew; /* The new scroll bar position */
858: /*
859: Set the scroll bar-specific parameters
860: */
861: WinQueryWindowPos(hwnd, &swp);
862: if (fHorz) { /* Horizontal scroll bar */
863: hwndSB = vhwndHSB;
864: cpels = swp.cx;
865: } else { /* Vertical scroll bar */
866: hwndSB = vhwndVSB;
867: cpels = swp.cy;
868: }
869: /*
870: Handle both scroll bars with one common routine
871:
872: Basically, the scroll bar has been set so that
873: the thumb value corresponds to the offset that
874: the bitmap is drawn from. So, to scroll by a
875: page, compute the number of pels of the page,
876: and move the thumb by that amount.
877:
878: This code is simplified by the fact that SB_SETPOS
879: will not allow the thumb to be set outside of the
880: range of the scroll bar, but will "stop" it at the
881: appropriate bound.
882: */
883: usOld = (USHORT) WinSendMsg(hwndSB, SBM_QUERYPOS, 0L, 0L);
884:
885: switch (sbCmd) {
886: case SB_PAGERIGHT: /* SB_PAGEDOWN */
887: WinSendMsg(hwndSB, SBM_SETPOS, MPFROMSHORT(usOld + cpels), 0L);
888: break;
889:
890: case SB_PAGELEFT: /* SB_PAGEUP */
891: WinSendMsg(hwndSB, SBM_SETPOS, MPFROMSHORT(usOld - cpels), 0L);
892: break;
893:
894: case SB_LINERIGHT: /* SB_LINEDOWN */
895: WinSendMsg(hwndSB, SBM_SETPOS, MPFROMSHORT(usOld + LINE), 0L);
896: break;
897:
898: case SB_LINELEFT: /* SB_LINEUP */
899: WinSendMsg(hwndSB, SBM_SETPOS, MPFROMSHORT(usOld - LINE), 0L);
900: break;
901:
902: case SB_SLIDERPOSITION:
903: /*
904: It would be nice to be consistent with the other
905: SB_ cases, but the problem is that when this message
906: is sent, the position is *already* set to "usPosition".
907:
908: So, just invalidate the entire region, and hope that most
909: of these types of operations will be large scrolls.
910: */
911: // WinSendMsg(hwndSB, SBM_SETPOS, MPFROMSHORT(LOUSHORT(mp2)), 0L);
912: WinInvalidateRect(hwnd, NULL, TRUE);
913: break;
914:
915: default:
916: return FALSE;
917: }
918: /*
919: Now, we find out where the new thumb position is,
920: scroll the window contents appropriately, and specify
921: SW_INVALIDATERGN so that the remainder will be
922: invalidated/repainted.
923: */
924: usNew = (USHORT) WinSendMsg(hwndSB, SBM_QUERYPOS, 0L, 0L);
925: if (fHorz)
926: WinScrollWindow(hwnd, (SHORT) (usOld - usNew), 0,
927: NULL, NULL, NULL, NULL, SW_INVALIDATERGN);
928: else
929: WinScrollWindow(hwnd, 0, (SHORT) (usNew - usOld),
930: NULL, NULL, NULL, NULL, SW_INVALIDATERGN);
931:
932: return TRUE;
933: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.