summaryrefslogtreecommitdiffstats
path: root/private/ole2ui32/resimage.cpp
blob: 4b98c4c850e0db98ff870ba893b144cb54cb2714 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
/*
 * RESIMAGE.CPP
 *
 * Implementation of the Results Image control for OLE 2.0 UI dialogs.
 * We need a separate control for dialogs in order to control the repaints
 * properly and to provide a clean message interface for the dialog
 * implementations.
 *
 * Copyright (c)1992 Microsoft Corporation, All Right Reserved
 */

#include "precomp.h"
#include "resimage.h"
#include "uiclass.h"
OLEDBGDATA

//Reference counter indicating how many times fResultImageInitialize has been
//successfully called
static UINT     uRegistered = 0;

//Bitmap and image dimensions for result images.
static HBITMAP  hBmpResults = NULL;
static UINT     cxBmpResult;
static UINT     cyBmpResult;

/*
 * FResultImageInitialize
 *
 * Purpose:
 *  Attempts to load result bitmaps for the current display driver
 *  for use in OLE 2.0 UI dialogs.  Also registers the ResultImage
 *  control class.
 *
 * Parameters:
 *  hInst           HINSTANCE instance of the DLL.
 *
 *  hPrevInst       HINSTANCE of the previous instance.  Used to
 *                  determine whether to register window classes or not.
 *
 * Return Value:
 *  BOOL            TRUE if all initialization succeeded, FALSE otherwise.
 */

#pragma code_seg(".text$initseg")

BOOL FResultImageInitialize(HINSTANCE hInst, HINSTANCE hPrevInst)
{
        int         cx, iBmp;
        HDC         hDC;
        BITMAP      bm;

        WNDCLASS        wc;

        /*
         * Determine the aspect ratio of the display we're currently
         * running on and load the appropriate bitmap into the global
         * hBmpResults (used from the ResultImage control only).
         *
         * By retrieving the logical Y extent of the display driver, you
         * only have limited possibilities:
         *      LOGPIXELSY      Display
         *      ----------------------------------------
         *         48             CGA    (unsupported)
         *         72             EGA
         *         96             VGA
         *        120             8514/a (i.e. HiRes VGA)
         */

        hDC=GetDC(NULL);

        if (NULL==hDC)
                return FALSE;

        cx=GetDeviceCaps(hDC, LOGPIXELSY);
        ReleaseDC(NULL, hDC);

        /*
         * Instead of single comparisons, check ranges instead, so in case
         * we get something funky, we'll act reasonable.
         */
        if (72 >=cx)             iBmp=IDB_RESULTSEGA;
        if (72 < cx && 120 > cx) iBmp=IDB_RESULTSVGA;
        if (120 <=cx)            iBmp=IDB_RESULTSHIRESVGA;

        if (NULL == hBmpResults)
        {
            hBmpResults=LoadBitmap(hInst, MAKEINTRESOURCE(iBmp));

            if (NULL==hBmpResults)
            {
                    //On error, fail loading the DLL
                    OleDbgOut1(TEXT("FResultImageInitialize:  Failed LoadBitmap.\r\n"));
                    return FALSE;
            }
            OleDbgOut4(TEXT("FResultImageInitialize:  Loaded hBmpResults\r\n"));

            // Now that we have the bitmap, calculate image dimensions
            GetObject(hBmpResults, sizeof(BITMAP), &bm);
            cxBmpResult = bm.bmWidth/CIMAGESX;
            cyBmpResult = bm.bmHeight;
        }


        // Only register class if we're the first instance
        if (hPrevInst)
                uRegistered++;
        else
        {
                // Static flag fRegistered guards against calling this function more
                // than once in the same instance

                if (0 == uRegistered)
                {
                        wc.lpfnWndProc   =ResultImageWndProc;
                        wc.cbClsExtra    =0;
                        wc.cbWndExtra    =CBRESULTIMAGEWNDEXTRA;
                        wc.hInstance     =hInst;
                        wc.hIcon         =NULL;
                        wc.hCursor       =LoadCursor(NULL, IDC_ARROW);
                        wc.hbrBackground =NULL;
                        wc.lpszMenuName  =NULL;
                        wc.style         =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;

                        wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE1);
                        uRegistered = RegisterClass(&wc) ? 1 : 0;

                        wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE2);
                        uRegistered = RegisterClass(&wc) ? 1 : 0;

                        wc.lpszClassName = TEXT(SZCLASSRESULTIMAGE3);
                        uRegistered = RegisterClass(&wc) ? 1 : 0;
                }
                else
                     uRegistered++;
        }

        return (uRegistered > 0);
}

#pragma code_seg()


/*
 * ResultImageUninitialize
 *
 * Purpose:
 *  Cleans up anything done in FResultImageInitialize, such as freeing
 *  the bitmaps.  Call from WEP.
 *
 * Parameters:
 *  None
 *
 * Return Value:
 *  None
 */

void ResultImageUninitialize(void)
{
    --uRegistered;
    if (0 == uRegistered)
    {
        if (NULL != hBmpResults)
        {
                DeleteObject(hBmpResults);
                hBmpResults = NULL;
        }
    }
}


/*
 * ResultImageWndProc
 *
 * Purpose:
 *  Window Procedure for the ResultImage custom control.  Only handles
 *  WM_CREATE, WM_PAINT, and private messages to manipulate the bitmap.
 *
 * Parameters:
 *  Standard
 *
 * Return Value:
 *  Standard
 */

LONG CALLBACK ResultImageWndProc(HWND hWnd, UINT iMsg,
        WPARAM wParam, LPARAM lParam)
{
        UINT            iBmp;
        PAINTSTRUCT     ps;
        HDC             hDC;

        //Handle standard Windows messages.
        switch (iMsg)
        {
                case WM_CREATE:
                        SetWindowWord(hWnd, RIWW_IMAGEINDEX, RESULTIMAGE_NONE);
                        return 0L;

                case WM_PAINT:
                        iBmp = GetWindowWord(hWnd, RIWW_IMAGEINDEX);
                        hDC = BeginPaint(hWnd, &ps);

                        RECT            rc;
                        UINT            x, y;
                        HDC             hDCDlg;
                        HBRUSH          hBr;
                        LOGBRUSH        lb;
                        HWND            hDlg;

                        /*
                         * Our job before using TransparentBlt is to figure out
                         * where to position the result image.  We place it centered
                         * on this control, so get our rect's center and subtract
                         * half of the image dimensions.
                         */
                        GetClientRect(hWnd, &rc);
                        x = (rc.right+rc.left-cxBmpResult)/2;
                        y = (rc.bottom+rc.top-cyBmpResult)/2;

                        // Get the backgroup color the dialog is using.
                        hDlg=GetParent(hWnd);
                        hDCDlg=GetDC(hDlg);
                        hBr = (HBRUSH)SendMessage(hDlg,
                                                                        WM_CTLCOLORDLG,
                                                                        (WPARAM)hDCDlg,
                                                                        (LPARAM)hDlg);
                        ReleaseDC(hDlg, hDCDlg);
                        GetObject(hBr, sizeof(LOGBRUSH), &lb);
                        SetBkColor(hDC, lb.lbColor);


                        if (RESULTIMAGE_NONE != iBmp)
                        {

                            TransparentBlt(hDC, x, y, hBmpResults, iBmp*cxBmpResult, 0,
                                    cxBmpResult, cyBmpResult, RGBTRANSPARENT);
                        }
                        else
                        {
                            FillRect(hDC, &rc, hBr);
                        }
                        EndPaint(hWnd, &ps);
                        break;

                case RIM_IMAGESET:
                        // wParam contains the new index.
                        iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);

                        // Validate the index before changing it and repainting
                        if (RESULTIMAGE_NONE==wParam ||
                                ((RESULTIMAGE_MIN <= wParam) && (RESULTIMAGE_MAX >= wParam)))
                        {
                                SetWindowWord(hWnd, RIWW_IMAGEINDEX, (WORD)wParam);
                                InvalidateRect(hWnd, NULL, FALSE);
                                UpdateWindow(hWnd);
                        }
                        // Return the previous index.
                        return iBmp;

                case RIM_IMAGEGET:
                        // Return the current index.
                        iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
                        return (LONG)iBmp;

                default:
                        return DefWindowProc(hWnd, iMsg, wParam, lParam);
        }

        return 0L;
}


/*
 * TransparentBlt
 *
 * Purpose:
 *  Given a DC, a bitmap, and a color to assume as transparent in that
 *  bitmap, BitBlts the bitmap to the DC letting the existing background
 *  show in place of the transparent color.
 *
 * Parameters:
 *  hDC             HDC on which to draw.
 *  x, y            UINT location at which to draw the bitmap
 *  hBmp            HBITMIP to draw from
 *  xOrg, yOrg      UINT coordinates from which to draw the bitamp
 *  cx, cy          UINT dimensions of the bitmap to Blt.
 *  cr              COLORREF to consider as transparent.
 *
 * Return Value:
 *  None
 */

void TransparentBlt(HDC hDC, UINT x, UINT y, HBITMAP hBmp, UINT xOrg, UINT yOrg,
        UINT cx, UINT cy, COLORREF cr)
{
        HDC         hDCSrc, hDCMid, hMemDC;
        HBITMAP     hBmpMono, hBmpT;
        HBRUSH      hBr, hBrT;
        COLORREF    crBack, crText;

        if (NULL == hBmp)
                return;

        // Get three intermediate DC's
        hDCSrc = CreateCompatibleDC(hDC);
        hDCMid = CreateCompatibleDC(hDC);
        hMemDC = CreateCompatibleDC(hDC);

        SelectObject(hDCSrc, hBmp);

        // Create a monochrome bitmap for masking
        hBmpMono=CreateCompatibleBitmap(hDCMid, cx, cy);
        SelectObject(hDCMid, hBmpMono);

        // Create a middle bitmap
        hBmpT=CreateCompatibleBitmap(hDC, cx, cy);
        SelectObject(hMemDC, hBmpT);

        // Create a monochrome mask where we have 0's in the image, 1's elsewhere.
        crBack=SetBkColor(hDCSrc, cr);
        BitBlt(hDCMid, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY);
        SetBkColor(hDCSrc, crBack);

        // Put the unmodified image in the temporary bitmap
        BitBlt(hMemDC, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY);

        // Create an select a brush of the background color
        hBr = CreateSolidBrush(GetBkColor(hDC));
        hBrT = (HBRUSH)SelectObject(hMemDC, hBr);

        // Force conversion of the monochrome to stay black and white.
        crText=SetTextColor(hMemDC, 0L);
        crBack=SetBkColor(hMemDC, RGB(255, 255, 255));

        /*
         * Where the monochrome mask is 1, Blt the brush; where the mono mask
         * is 0, leave the destination untouches.  This results in painting
         * around the image with the background brush.  We do this first
         * in the temporary bitmap, then put the whole thing to the screen.
         */
        BitBlt(hMemDC, 0, 0, cx, cy, hDCMid, 0, 0, ROP_DSPDxax);
        BitBlt(hDC,    x, y, cx, cy, hMemDC, 0, 0, SRCCOPY);

        SetTextColor(hMemDC, crText);
        SetBkColor(hMemDC, crBack);

        SelectObject(hMemDC, hBrT);
        DeleteObject(hBr);

        DeleteDC(hMemDC);
        DeleteDC(hDCSrc);
        DeleteDC(hDCMid);
        DeleteObject(hBmpT);
        DeleteObject(hBmpMono);
}