1 /* Sarien - A Sierra AGI resource interpreter engine
2 * Copyright (C) 1999-2001 Stuart George and Claudio Matsuoka
3 *
4 * $Id: wince.cpp,v 1.3.2.1 2001/11/10 12:13:54 cmatsuoka Exp $
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; see docs/COPYING for further details.
9 */
10
11 /*
12 * Win32 port by Felipe Rosinha <rosinha@helllabs.org>
13 */
14
15 /*
16 * Massively modified by Vasyl Tsvirkunov <vasyl@pacbell.net> for
17 * Pocket PC/WinCE port
18 */
19
20 #include <ctype.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <windows.h>
24 #include <mmsystem.h>
25 #include <stdio.h>
26 #include <commctrl.h>
27 #include <aygshell.h>
28 #include "gx.h"
29
30 #include "sarien.h"
31 #include "graphics.h"
32 #include "keyboard.h"
33 #include "console.h"
34 #include "text.h"
35 /* Prevent name conflict */
36 #undef snprintf
37 #include "win32.h"
38
39 #include "resource.h"
40
41 #define USE_F_KEYS
42 #define SMOOTH
43
44 static LPTSTR szAppName = TEXT("Pocket Sarien");
45 static GXDisplayProperties gxdp;
46 static GXKeyList gxkl;
47 static bool active = true;
48
49 static HWND hwndMB = NULL;
50
51 typedef unsigned char UBYTE;
52 static UBYTE* screen;
53 #ifdef SMOOTH
54 static UBYTE* palRed;
55 static UBYTE* palGreen;
56 static UBYTE* palBlue;
57 #else
58 static unsigned short* pal;
59 #endif
60
61 static bool bmono;
62 static bool b565;
63 static bool b555;
64
65 static UBYTE invert = 0;
66 static int colorscale = 0;
67
68 #define COLORCONV565(r,g,b) (((r&0xf8)<<(11-3))|((g&0xfc)<<(5-2))|((b&0xf8)>>3))
69 #define COLORCONV555(r,g,b) (((r&0xf8)<<(10-3))|((g&0xf8)<<(5-2))|((b&0xf8)>>3))
70 #define COLORCONVMONO(r,g,b) ((((3*r>>3)+(g>>1)+(b>>3))>>colorscale)^invert)
71
72 static int wince_init_vidmode (void);
73 static int wince_deinit_vidmode(void);
74 static void wince_put_block (int, int, int, int);
75 static void wince_put_pixels (int, int, int, BYTE *);
76 static int wince_keypress (void);
77 static int wince_get_key (void);
78 static void wince_new_timer (void);
79
80 LRESULT CALLBACK WindowProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam);
81
82 #ifdef USE_F_KEYS
83 void setup_extra_windows(HWND hwndTop);
84 void adjust_extra_windows();
85 HWND hwndFKeys;
86 #endif
87
88 static struct gfx_driver gfx_wince =
89 {
90 wince_init_vidmode,
91 wince_deinit_vidmode,
92 wince_put_block,
93 wince_put_pixels,
94 wince_new_timer,
95 wince_keypress,
96 wince_get_key
97 };
98
99
100 extern "C" struct gfx_driver *gfx;
101
init_machine(int argc,char ** argv)102 int init_machine(int argc, char **argv)
103 {
104 gfx = &gfx_wince;
105 return err_OK;
106 }
107
deinit_machine()108 int deinit_machine()
109 {
110 return err_OK;
111 }
112
set_palette(int ent,UBYTE r,UBYTE g,UBYTE b)113 void set_palette(int ent, UBYTE r, UBYTE g, UBYTE b)
114 {
115 if (ent >= 256)
116 return;
117 #ifdef SMOOTH
118 palRed[ent] = r;
119 palGreen[ent] = g;
120 palBlue[ent] = b;
121 #else
122 if(b565)
123 pal[ent] = COLORCONV565(r,g,b);
124 else if(b555)
125 pal[ent] = COLORCONV555(r,g,b);
126 else if(bmono)
127 pal[ent] = COLORCONVMONO(r,g,b);
128 #endif
129 }
130
131
wince_init_vidmode()132 static int wince_init_vidmode()
133 {
134 WNDCLASS wc;
135
136 wc.style = CS_HREDRAW | CS_VREDRAW;
137 wc.lpfnWndProc = WindowProc;
138 wc.cbClsExtra = 0;
139 wc.cbWndExtra = 0;
140 wc.hInstance = GetModuleHandle(NULL);
141 wc.hIcon = (HICON)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SARIEN));
142 wc.hCursor = NULL;
143 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
144 wc.lpszMenuName = NULL;
145 wc.lpszClassName = szAppName;
146 RegisterClass(&wc);
147
148 hwndMain = CreateWindow(szAppName,
149 szAppName,
150 WS_VISIBLE,
151 0,
152 0,
153 GetSystemMetrics(SM_CXSCREEN),
154 GetSystemMetrics(SM_CYSCREEN),
155 NULL,
156 NULL,
157 GetModuleHandle(NULL),
158 NULL);
159
160 if(!hwndMain)
161 return err_Unk;
162
163 SHMENUBARINFO smbi;
164 smbi.cbSize = sizeof(smbi);
165 smbi.hwndParent = hwndMain;
166 smbi.dwFlags = 0;
167 smbi.nToolBarId = IDM_MENU;
168 smbi.hInstRes = GetModuleHandle(NULL);
169 smbi.nBmpId = 0;
170 smbi.cBmpImages = 0;
171 smbi.hwndMB = NULL;
172 BOOL res = SHCreateMenuBar(&smbi);
173 hwndMB = smbi.hwndMB;
174
175 screen = new UBYTE[GFX_WIDTH*GFX_HEIGHT];
176 #ifdef SMOOTH
177 palRed = new UBYTE[256];
178 palGreen = new UBYTE[256];
179 palBlue = new UBYTE[256];
180 if(!palRed || !palGreen || !palBlue)
181 return err_Unk;
182 #else
183 pal = new unsigned short[256];
184 if(!pal)
185 return err_Unk;
186 #endif
187
188 if(!screen)
189 return err_Unk;
190
191 memset(screen, 0, GFX_WIDTH*GFX_HEIGHT);
192
193 GXOpenDisplay(hwndMain, GX_FULLSCREEN);
194 GXOpenInput();
195
196 SetWindowPos(hwndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
197 SetForegroundWindow(hwndMain);
198 SHFullScreen(hwndMain, SHFS_SHOWSIPBUTTON);
199 SHFullScreen(hwndMain, SHFS_HIDETASKBAR);
200
201 gxdp = GXGetDisplayProperties();
202 gxkl = GXGetDefaultKeys(GX_NORMALKEYS);
203
204
205 bmono = (gxdp.ffFormat & kfDirect) && (gxdp.cBPP <= 8);
206 b565 = (gxdp.ffFormat & kfDirect565) != 0;
207 b555 = (gxdp.ffFormat & kfDirect555) != 0;
208 if(bmono)
209 {
210 if(gxdp.ffFormat & kfDirectInverted)
211 invert = (1<<gxdp.cBPP)-1;
212 colorscale = gxdp.cBPP < 8 ? 8-gxdp.cBPP : 0;
213 }
214
215 int i;
216 for(i=0; i<16; i++)
217 set_palette(i, palette[i*3+0]<<2, palette[i*3+1]<<2, palette[i*3+2]<<2);
218 for(i=17; i<256; i++)
219 set_palette(i, 0, 255, 0);
220
221 #ifdef USE_F_KEYS
222 setup_extra_windows(hwndMain);
223 #endif
224
225 return err_OK;
226 }
227
process_events()228 static void INLINE process_events()
229 {
230 MSG msg;
231 while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
232 {
233 TranslateMessage(&msg);
234 DispatchMessage(&msg);
235 }
236 }
237
wince_deinit_vidmode(void)238 static int wince_deinit_vidmode(void)
239 {
240 GXCloseInput();
241 GXCloseDisplay();
242
243 delete[] screen;
244 #ifdef SMOOTH
245 delete[] palRed;
246 delete[] palGreen;
247 delete[] palBlue;
248 #else
249 delete[] pal;
250 #endif
251
252
253 PostMessage(hwndMain, WM_QUIT, 0, 0);
254 return err_OK;
255 }
256
257
258 #define TICK_SECONDS 18
259 #define TICK_IN_MSEC (1000 / (TICK_SECONDS))
260
wince_new_timer()261 static void wince_new_timer()
262 {
263 DWORD now;
264 static DWORD last = 0;
265
266 now = GetTickCount();
267
268 while (now - last < TICK_IN_MSEC)
269 {
270 Sleep (TICK_IN_MSEC - (now - last));
271 now = GetTickCount ();
272 }
273 last = now;
274
275 process_events ();
276 }
277
278 #define REPEATED_KEYMASK (1<<30)
279 #define RELEASED_KEYMASK (1<<31)
280 #define KEY_QUEUE_SIZE 16
281
282 static struct{
283 int start;
284 int end;
285 int queue[KEY_QUEUE_SIZE];
286 } g_key_queue = { 0, 0 };
287
288
289 #define key_enqueue(k) do { \
290 g_key_queue.queue[g_key_queue.end++] = (k); \
291 g_key_queue.end %= KEY_QUEUE_SIZE; \
292 } while (0)
293
294 #define key_dequeue(k) do { \
295 (k) = g_key_queue.queue[g_key_queue.start++]; \
296 g_key_queue.start %= KEY_QUEUE_SIZE; \
297 } while (0)
298
299
wince_keypress(void)300 static int wince_keypress(void)
301 {
302 process_events();
303 return (g_key_queue.start != g_key_queue.end);
304 }
305
wince_get_key(void)306 static int wince_get_key(void)
307 {
308 int k;
309 while (!wince_keypress())
310 wince_new_timer();
311 key_dequeue(k);
312 return k;
313 }
314
315
wince_put_pixels(int x,int y,int w,BYTE * p)316 static void wince_put_pixels(int x, int y, int w, BYTE *p)
317 {
318 memcpy(screen+x+y*GFX_WIDTH, p, w);
319 }
320
wince_put_block(int x1,int y1,int x2,int y2)321 static void wince_put_block(int x1, int y1, int x2, int y2)
322 {
323 if(!active)
324 return;
325
326 /* Somehow this function gets called with unchecked bounds causing visual artefacts */
327 if(x2 > 319)
328 x2 = 319;
329 if(y2 > 199)
330 y2 = 199;
331
332 static UBYTE *src;
333 static UBYTE *dst;
334
335 static UBYTE *scraddr;
336 static UBYTE *scr_ptr;
337
338 static UBYTE *scr_ptr_limit;
339 static UBYTE *src_limit;
340
341 static long pixelstep;
342 static long linestep;
343
344 // Special code is used to deal with packed pixels in monochrome mode
345 static UBYTE bitmask;
346 static int bitshift;
347
348 #ifdef SMOOTH
349 x1 &= ~3;
350 #endif
351
352 scr_ptr = screen + x1 + y1*GFX_WIDTH;
353 scr_ptr_limit = screen + x2 + y2*GFX_WIDTH;
354
355 linestep = gxdp.cbyPitch;
356 pixelstep = gxdp.cbxPitch;
357
358 if(bmono)
359 {
360 if(pixelstep == 0)
361 return; // unsupported screen geometry
362 // this will work on mono iPAQ and @migo, don't know about any others
363 bitshift = 0;
364 bitmask = (1<<gxdp.cBPP)-1;
365 linestep = (pixelstep > 0) ? -1 : 1;
366 }
367
368
369 scraddr = (UBYTE*)GXBeginDraw();
370 if(scraddr)
371 {
372 if(bmono)
373 {
374 // Some partial pixel voodoo. I don't know if this works in all cases.
375 scraddr += (x1*3/4)*pixelstep;
376 int full = (y1*gxdp.cBPP)>>3;
377 int partial = (y1*gxdp.cBPP)&7;
378 scraddr += full*linestep;
379 bitshift += gxdp.cBPP*partial;
380 bitmask <<= gxdp.cBPP*partial;
381 if(linestep < 0)
382 scraddr += (pixelstep-1);
383 }
384 else
385 scraddr += (x1*3/4)*pixelstep + y1*linestep;
386 src_limit = scr_ptr + x2-x1+1;
387
388 while(scr_ptr < scr_ptr_limit)
389 {
390 src = scr_ptr;
391 dst = scraddr;
392 while(src < src_limit)
393 {
394 #ifdef SMOOTH
395 /* Let's see how fast that CPU is */
396 UBYTE r, g, b;
397 r = (3*palRed[*(src+0)] + palRed[*(src+1)])>>2;
398 g = (3*palGreen[*(src+0)] + palGreen[*(src+1)])>>2;
399 b = (3*palBlue[*(src+0)] + palBlue[*(src+1)])>>2;
400
401 if(b565)
402 *(unsigned short*)dst = COLORCONV565(r,g,b);
403 else if(b555)
404 *(unsigned short*)dst = COLORCONV555(r,g,b);
405 else if(bmono)
406 *dst = (*dst & ~bitmask) | (COLORCONVMONO(r,g,b)<<bitshift);
407
408 dst += pixelstep;
409
410 r = (palRed[*(src+1)] + palRed[*(src+2)])>>1;
411 g = (palGreen[*(src+1)] + palGreen[*(src+2)])>>1;
412 b = (palBlue[*(src+1)] + palBlue[*(src+2)])>>1;
413
414 if(b565)
415 *(unsigned short*)dst = COLORCONV565(r,g,b);
416 else if(b555)
417 *(unsigned short*)dst = COLORCONV555(r,g,b);
418 else if(bmono)
419 *dst = (*dst & ~bitmask) | (COLORCONVMONO(r,g,b)<<bitshift);
420
421 dst += pixelstep;
422
423 r = (palRed[*(src+2)] + 3*palRed[*(src+3)])>>2;
424 g = (palGreen[*(src+2)] + 3*palGreen[*(src+3)])>>2;
425 b = (palBlue[*(src+2)] + 3*palBlue[*(src+3)])>>2;
426
427 if(b565)
428 *(unsigned short*)dst = COLORCONV565(r,g,b);
429 else if(b555)
430 *(unsigned short*)dst = COLORCONV555(r,g,b);
431 else if(bmono)
432 *dst = (*dst & ~bitmask) | (COLORCONVMONO(r,g,b)<<bitshift);
433
434 dst += pixelstep;
435
436 src += 4;
437 #else
438 if((unsigned long)src & 3)
439 {
440 if(bmono)
441 *dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
442 else
443 *(unsigned short*)dst = pal[*src];
444 dst += pixelstep;
445 }
446 src ++;
447 #endif
448 }
449 if(bmono)
450 {
451 bitshift += gxdp.cBPP;
452 if(bitshift >= 8)
453 {
454 bitshift = 0;
455 bitmask = (1<<gxdp.cBPP)-1;
456 scraddr += linestep;
457 }
458 else
459 bitmask <<= gxdp.cBPP;
460 }
461 else
462 scraddr += linestep;
463 scr_ptr += GFX_WIDTH;
464 src_limit += GFX_WIDTH;
465 }
466
467 GXEndDraw();
468 }
469 }
470
471
WindowProc(HWND hwnd,UINT nMsg,WPARAM wParam,LPARAM lParam)472 LRESULT CALLBACK WindowProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
473 {
474 HDC hDC;
475 PAINTSTRUCT ps;
476 int key = 0;
477 static SHACTIVATEINFO sai;
478 int x, y;
479 RECT rc;
480
481 switch (nMsg)
482 {
483 case WM_CREATE:
484 memset(&sai, 0, sizeof(sai));
485 SHSipPreference(hwnd, SIP_INPUTDIALOG);
486 return 0;
487 case WM_DESTROY:
488 wince_deinit_vidmode ();
489 exit (-1);
490 return 0;
491 case WM_ERASEBKGND:
492 {
493 GetClientRect(hwnd, &rc);
494 rc.top = 200;
495 hDC = GetDC(hwnd);
496 if(rc.top < rc.bottom)
497 FillRect(hDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
498 ReleaseDC(hwnd, hDC);
499 }
500 return 1;
501 case WM_PAINT:
502 hDC = BeginPaint (hwndMain, &ps);
503 EndPaint (hwndMain, &ps);
504 SHSipPreference(hwndMain, SIP_UP); /* Hack! */
505 #ifdef USE_F_KEYS
506 adjust_extra_windows();
507 #endif
508 /* It does not happen often but I don't want to see tooltip traces */
509 wince_put_block(0, 0, 319, 199);
510 return 0;
511 case WM_ACTIVATE:
512 if(!active)
513 {
514 active = true;
515 GXResume();
516 }
517 SHHandleWMActivate(hwnd, wParam, lParam, &sai, SHA_INPUTDIALOG);
518 #ifdef USE_F_KEYS
519 adjust_extra_windows();
520 #endif
521 return 0;
522 case WM_HIBERNATE:
523 if(active)
524 {
525 active = false;
526 GXSuspend();
527 }
528 return 0;
529 case WM_SETTINGCHANGE:
530 SHHandleWMSettingChange(hwnd, wParam, lParam, &sai);
531 #ifdef USE_F_KEYS
532 adjust_extra_windows();
533 #endif
534 return 0;
535 case WM_COMMAND:
536 switch(wParam)
537 {
538 case IDC_ABOUT:
539 message_box("Pocket Sarien R4 (" __DATE__ ")\n\n"
540 "Ported by Vasyl Tsvirkunov\n"
541 "http://pocketatari.\n"
542 " retrogames.com\n\n"
543 "Visit Sarien homepage at\n"
544 "http://sarien.sourceforge.net");
545 break;
546 case IDC_EXIT:
547 DestroyWindow(hwndMain);
548 break;
549 }
550 return 0;
551
552 /* Multimedia functions
553 * (Damn! The CALLBACK_FUNCTION parameter doesn't work!)
554 */
555 /* VT: I think it works but I don't care to test at this moment */
556 case MM_WOM_DONE:
557 flush_sound ((PWAVEHDR) lParam);
558 return 0;
559
560 case WM_LBUTTONDOWN:
561 if(HIWORD(lParam)<200)
562 {
563 key = BUTTON_LEFT;
564 mouse.button = TRUE;
565 mouse.x = LOWORD(lParam)*4/3;
566 mouse.y = HIWORD(lParam);
567 }
568 break;
569
570 case WM_RBUTTONDOWN:
571 if(HIWORD(lParam)<200)
572 {
573 key = BUTTON_RIGHT;
574 mouse.button = TRUE;
575 mouse.x = LOWORD(lParam)*4/3;
576 mouse.y = HIWORD(lParam);
577 }
578 break;
579
580 case WM_LBUTTONUP:
581 case WM_RBUTTONUP:
582 mouse.button = FALSE;
583 return 0;
584
585 case WM_MOUSEMOVE:
586 if(HIWORD(lParam)<200)
587 {
588 mouse.x = LOWORD(lParam)*4/3;
589 mouse.y = HIWORD(lParam);
590 }
591 return 0;
592
593 case WM_KEYDOWN:
594 switch(wParam)
595 {
596 case VK_UP:
597 if(!(lParam & REPEATED_KEYMASK))
598 key = KEY_UP;
599 break;
600 case VK_LEFT:
601 if(!(lParam & REPEATED_KEYMASK))
602 key = KEY_LEFT;
603 break;
604 case VK_DOWN:
605 if(!(lParam & REPEATED_KEYMASK))
606 key = KEY_DOWN;
607 break;
608 case VK_RIGHT:
609 if(!(lParam & REPEATED_KEYMASK))
610 key = KEY_RIGHT;
611 break;
612 case VK_HOME:
613 if(!(lParam & REPEATED_KEYMASK))
614 key = KEY_UP_LEFT;
615 break;
616 case VK_PRIOR:
617 if(!(lParam & REPEATED_KEYMASK))
618 key = KEY_UP_RIGHT;
619 break;
620 case VK_NEXT:
621 if(!(lParam & REPEATED_KEYMASK))
622 key = KEY_DOWN_RIGHT;
623 break;
624 case VK_END:
625 if(!(lParam & REPEATED_KEYMASK))
626 key = KEY_DOWN_LEFT;
627 break;
628 case VK_F1:
629 key = 0x3b00;
630 break;
631 case VK_F2:
632 key = 0x3c00;
633 break;
634 case VK_F3:
635 key = 0x3d00;
636 break;
637 case VK_F4:
638 key = 0x3e00;
639 break;
640 case VK_F5:
641 key = 0x3f00;
642 break;
643 case VK_F6:
644 key = 0x4000;
645 break;
646 case VK_F7:
647 key = 0x4100;
648 break;
649 case VK_F8:
650 key = 0x4200;
651 break;
652 case VK_F9:
653 key = 0x4300;
654 break;
655 case VK_F10:
656 key = 0x4400;
657 break;
658 case VK_SNAPSHOT:
659 key = KEY_PRIORITY;
660 break;
661 default:
662 if(key == gxkl.vkA)
663 {
664 key = KEY_ENTER;
665 break;
666 }
667 else if(key == gxkl.vkB)
668 {
669 key = KEY_ESCAPE;
670 break;
671 }
672 #ifdef USE_CONSOLE
673 else if(key == gxkl.vkC)
674 {
675 key = CONSOLE_ACTIVATE_KEY;
676 break;
677 }
678 #endif
679 };
680 break;
681
682 case WM_CHAR:
683 if(!(lParam & RELEASED_KEYMASK)) /* pressed? */
684 {
685 key = (int)wParam;
686 if(key == '\\')
687 key = KEY_ESCAPE; /* menu */
688 }
689 else
690 return 0;
691 break;
692 };
693
694 /* Keyboard message handled */
695 if (key) {
696 key_enqueue (key);
697 return 0;
698 }
699
700 return DefWindowProc (hwnd, nMsg, wParam, lParam);
701 }
702
703 #ifdef USE_F_KEYS
704 /* Window for F-key input. Hack but some people asked for it. */
FWindowProc(HWND hwnd,UINT nMsg,WPARAM wParam,LPARAM lParam)705 LRESULT CALLBACK FWindowProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
706 {
707 switch (nMsg)
708 {
709 case WM_CREATE:
710 return 0;
711 case WM_PAINT:
712 {
713 HDC hDC;
714 PAINTSTRUCT ps;
715 RECT rc;
716 hDC = BeginPaint(hwnd, &ps);
717 GetClientRect(hwnd, &rc);
718 HGDIOBJ oldPen = SelectObject(hDC, (HGDIOBJ)GetStockObject(BLACK_PEN));
719 HGDIOBJ oldBr = SelectObject(hDC, (HGDIOBJ)GetStockObject(WHITE_BRUSH));
720 HGDIOBJ oldFont = SelectObject(hDC, (HGDIOBJ)GetStockObject(SYSTEM_FONT));
721 int rcWidth = rc.right-rc.left;
722 RECT rcItem;
723 rcItem.top = rc.top;
724 rcItem.bottom = rc.bottom;
725 POINT pts[2];
726 pts[0].y = rc.top;
727 pts[1].y = rc.bottom;
728 TCHAR text[4];
729 for(int i=0; i<10; i++)
730 {
731 wsprintf(text, TEXT("F%d"), i+1);
732 rcItem.left = rc.left+rcWidth*i/10;
733 rcItem.right = rc.left+rcWidth*(i+1)/10;
734 pts[0].x = pts[1].x = rcItem.right;
735 Polyline(hDC, pts, 2);
736 DrawText(hDC, text, -1, &rcItem, DT_CENTER|DT_VCENTER);
737 }
738 SelectObject(hDC, oldPen);
739 SelectObject(hDC, oldBr);
740 SelectObject(hDC, oldFont);
741 EndPaint(hwnd, &ps);
742 }
743 return 0;
744 case WM_LBUTTONDOWN:
745 {
746 int x = LOWORD(lParam);
747 RECT rc; GetWindowRect(hwnd, &rc);
748 int fnum = x*10/(rc.right-rc.left);
749 PostMessage(hwndMain, WM_KEYDOWN, VK_F1+fnum, 0);
750 }
751 return 0;
752 }
753
754 return DefWindowProc(hwnd, nMsg, wParam, lParam);
755 }
756
setup_extra_windows(HWND hwndTop)757 void setup_extra_windows(HWND hwndTop)
758 {
759 LPTSTR fkeyname = TEXT("fkeys");
760
761 WNDCLASS wc;
762 wc.style = CS_HREDRAW | CS_VREDRAW;
763 wc.lpfnWndProc = FWindowProc;
764 wc.cbClsExtra = 0;
765 wc.cbWndExtra = 0;
766 wc.hInstance = GetModuleHandle(NULL);
767 wc.hIcon = NULL;
768 wc.hCursor = NULL;
769 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
770 wc.lpszMenuName = NULL;
771 wc.lpszClassName = fkeyname;
772 RegisterClass(&wc);
773
774 hwndFKeys = CreateWindow(fkeyname,
775 fkeyname,
776 WS_VISIBLE|WS_CHILD,
777 0,
778 200,
779 GetSystemMetrics(SM_CXSCREEN),
780 20,
781 hwndTop,
782 (HMENU)100,
783 GetModuleHandle(NULL),
784 NULL);
785 }
786
adjust_extra_windows()787 void adjust_extra_windows()
788 {
789 SIPINFO si;
790 si.cbSize = sizeof(SIPINFO);
791 SHSipInfo(SPI_GETSIPINFO, 0, &si, 0);
792 if(si.fdwFlags & SIPF_ON)
793 {
794 int bottom = si.rcVisibleDesktop.bottom;
795 SetWindowPos(hwndFKeys, 0, 0, 200, GetSystemMetrics(SM_CXSCREEN), bottom-200,
796 SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER);
797 }
798 }
799 #endif
800