2 * Copyright 1998 Douglas Ridgway
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 static HINSTANCE hInst
;
27 static WCHAR szAppName
[5] = {'V','i','e','w',0};
28 static WCHAR szTitle
[80];
31 static HENHMETAFILE enhmf
;
32 static int deltax
= 0, deltay
= 0;
33 static int width
= 0, height
= 0;
34 static BOOL isAldus
, isEnhanced
;
48 #define APMHEADER_KEY 0x9AC6CDD7l
51 static BOOL
FileOpen(HWND hWnd
, WCHAR
*fn
, int fnsz
)
53 static const WCHAR filter
[] = {'M','e','t','a','f','i','l','e','s','\0','*','.','w','m','f',';','*','.','e','m','f','\0',0};
54 OPENFILENAMEW ofn
= { sizeof(OPENFILENAMEW
),
55 0, 0, NULL
, NULL
, 0, 0, NULL
,
56 fnsz
, NULL
, 0, NULL
, NULL
,
57 OFN_SHOWHELP
, 0, 0, NULL
, 0, NULL
};
58 ofn
.lpstrFilter
= filter
;
64 return GetOpenFileNameW(&ofn
);
67 static BOOL
FileIsEnhanced( LPCWSTR szFileName
)
73 handle
= CreateFileW( szFileName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
74 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0 );
75 if (handle
== INVALID_HANDLE_VALUE
)
78 if (!ReadFile( handle
, &enh
, sizeof(ENHMETAHEADER
), &size
, NULL
) || size
!= sizeof(ENHMETAHEADER
) )
80 CloseHandle( handle
);
83 CloseHandle( handle
);
86 return (enh
.dSignature
== ENHMETA_SIGNATURE
);
89 static BOOL
FileIsPlaceable( LPCWSTR szFileName
)
95 handle
= CreateFileW( szFileName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
96 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0 );
97 if (handle
== INVALID_HANDLE_VALUE
)
100 if (!ReadFile( handle
, &apmh
, sizeof(APMFILEHEADER
), &size
, NULL
) || size
!= sizeof(APMFILEHEADER
))
102 CloseHandle( handle
);
105 CloseHandle( handle
);
107 /* Is it placeable? */
108 return (apmh
.key
== APMHEADER_KEY
);
111 static HMETAFILE
GetPlaceableMetaFile( LPCWSTR szFileName
)
115 APMFILEHEADER APMHeader
;
123 handle
= CreateFileW( szFileName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
124 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0 );
125 if (handle
== INVALID_HANDLE_VALUE
)
128 if (!ReadFile( handle
, &APMHeader
, sizeof(APMFILEHEADER
), &size
, NULL
) || size
!= sizeof(APMFILEHEADER
))
130 CloseHandle( handle
);
134 p
= (WORD
*) &APMHeader
;
138 if (checksum
!= APMHeader
.checksum
) {
140 sprintf(msg
, "Computed checksum %04x != stored checksum %04x\n",
141 checksum
, APMHeader
.checksum
);
142 MessageBoxA(hMainWnd
, msg
, "Checksum failed", MB_OK
);
143 CloseHandle( handle
);
147 if (!ReadFile( handle
, &mfHeader
, sizeof(METAHEADER
), &size
, NULL
) || size
!= sizeof(METAHEADER
))
149 CloseHandle( handle
);
153 if (!(lpData
= GlobalAlloc(GPTR
, (mfHeader
.mtSize
* 2L))))
155 CloseHandle( handle
);
159 SetFilePointer( handle
, sizeof(APMFILEHEADER
), NULL
, FILE_BEGIN
);
160 if (!ReadFile(handle
, lpData
, mfHeader
.mtSize
* 2, &size
, NULL
) || size
!= mfHeader
.mtSize
* 2)
163 CloseHandle( handle
);
166 CloseHandle( handle
);
168 if (!(hmf
= SetMetaFileBitsEx(mfHeader
.mtSize
*2, lpData
)))
172 width
= APMHeader
.bbox
.Right
- APMHeader
.bbox
.Left
;
173 height
= APMHeader
.bbox
.Bottom
- APMHeader
.bbox
.Top
;
175 /* printf("Ok! width %d height %d inch %d\n", width, height, APMHeader.inch); */
176 hdc
= GetDC(hMainWnd
);
177 width
= width
* GetDeviceCaps(hdc
, LOGPIXELSX
)/APMHeader
.inch
;
178 height
= height
* GetDeviceCaps(hdc
,LOGPIXELSY
)/APMHeader
.inch
;
179 ReleaseDC(hMainWnd
, hdc
);
186 static void DoOpenFile(LPCWSTR filename
)
188 if (!filename
) return;
190 isAldus
= FileIsPlaceable(filename
);
192 hmf
= GetPlaceableMetaFile(filename
);
195 isEnhanced
= FileIsEnhanced(filename
);
197 enhmf
= GetEnhMetaFileW(filename
);
199 hmf
= GetMetaFileW(filename
);
200 GetClientRect(hMainWnd
, &r
);
201 width
= r
.right
- r
.left
;
202 height
= r
.bottom
- r
.top
;
204 InvalidateRect( hMainWnd
, NULL
, TRUE
);
207 static LRESULT CALLBACK
WndProc(HWND hwnd
, UINT uMessage
, WPARAM wparam
, LPARAM lparam
)
214 BeginPaint(hwnd
, &ps
);
215 SetMapMode(ps
.hdc
, MM_ANISOTROPIC
);
216 /* Set the window extent to a sane value in case the metafile doesn't */
217 SetWindowExtEx(ps
.hdc
, width
, height
, NULL
);
218 SetViewportExtEx(ps
.hdc
, width
, height
, NULL
);
219 SetViewportOrgEx(ps
.hdc
, deltax
, deltay
, NULL
);
220 if (isEnhanced
&& enhmf
)
223 GetClientRect(hwnd
, &r
);
224 PlayEnhMetaFile(ps
.hdc
, enhmf
, &r
);
227 PlayMetaFile(ps
.hdc
, hmf
);
232 case WM_COMMAND
: /* message: command from application menu */
233 switch (LOWORD(wparam
))
237 WCHAR filename
[MAX_PATH
];
238 if (FileOpen(hwnd
, filename
, sizeof(filename
)/sizeof(WCHAR
)))
239 DoOpenFile(filename
);
243 case IDM_SET_EXT_TO_WIN
:
246 GetClientRect(hwnd
, &r
);
247 width
= r
.right
- r
.left
;
248 height
= r
.bottom
- r
.top
;
250 InvalidateRect( hwnd
, NULL
, TRUE
);
257 InvalidateRect( hwnd
, NULL
, TRUE
);
261 InvalidateRect( hwnd
, NULL
, TRUE
);
265 InvalidateRect( hwnd
, NULL
, TRUE
);
269 InvalidateRect( hwnd
, NULL
, TRUE
);
277 return DefWindowProcW(hwnd
, uMessage
, wparam
, lparam
);
281 case WM_DESTROY
: /* message: window being destroyed */
285 default: /* Passes it on if unprocessed */
286 return DefWindowProcW(hwnd
, uMessage
, wparam
, lparam
);
291 static BOOL
InitApplication(HINSTANCE hInstance
)
295 /* Load the application description strings */
296 LoadStringW(hInstance
, IDS_DESCRIPTION
, szTitle
, sizeof(szTitle
)/sizeof(WCHAR
));
298 /* Fill in window class structure with parameters that describe the
301 wc
.cbSize
= sizeof(WNDCLASSEXW
);
302 wc
.style
= CS_HREDRAW
| CS_VREDRAW
; /* Class style(s) */
303 wc
.lpfnWndProc
= WndProc
; /* Window Procedure */
304 wc
.cbClsExtra
= 0; /* No per-class extra data */
305 wc
.cbWndExtra
= 0; /* No per-window extra data */
306 wc
.hInstance
= hInstance
; /* Owner of this class */
309 wc
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
310 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1); /* Default color */
311 wc
.lpszMenuName
= szAppName
; /* Menu name from .rc */
312 wc
.lpszClassName
= szAppName
; /* Name to register as */
314 if (!RegisterClassExW(&wc
)) return FALSE
;
316 /* Call module specific initialization functions here */
321 static BOOL
InitInstance(HINSTANCE hInstance
, int nCmdShow
)
323 /* Save the instance handle in a global variable for later use */
326 /* Create main window */
327 hMainWnd
= CreateWindowW(szAppName
, /* See RegisterClass() call */
328 szTitle
, /* window title */
329 WS_OVERLAPPEDWINDOW
, /* Window style */
330 CW_USEDEFAULT
, 0, /* positioning */
331 CW_USEDEFAULT
, 0, /* size */
332 NULL
, /* Overlapped has no parent */
333 NULL
, /* Use the window class menu */
340 /* Call module specific instance initialization functions here */
342 /* show the window, and paint it for the first time */
343 ShowWindow(hMainWnd
, nCmdShow
);
344 UpdateWindow(hMainWnd
);
349 static void HandleCommandLine(LPWSTR cmdline
)
351 /* skip white space */
352 while (*cmdline
== ' ') cmdline
++;
356 /* file name is passed on the command line */
357 if (cmdline
[0] == '"')
360 cmdline
[lstrlenW(cmdline
) - 1] = 0;
366 int APIENTRY
wWinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
, LPWSTR lpCmdLine
, int nCmdShow
)
370 /* Other instances of app running? */
373 /* stuff to be done once */
374 if (!InitApplication(hInstance
))
376 return FALSE
; /* exit */
380 /* stuff to be done every time */
381 if (!InitInstance(hInstance
, nCmdShow
))
386 HandleCommandLine(lpCmdLine
);
389 /* Acquire and dispatch messages until a WM_QUIT message is received */
390 while (GetMessageW(&msg
, NULL
, 0, 0))
392 TranslateMessage(&msg
);
393 DispatchMessageW(&msg
);