📄 ui_win32.c
字号:
/* This file actually implements three drivers (win32 and DirectX windowed/fullscreen) drivers, because they have a lot of common stuff. */#include <config.h>#ifdef WIN32_DRIVER#include <windows.h>#ifdef DDRAW_DRIVER#include <ddraw.h>#endif#include <malloc.h>#include <string.h>#include <stdio.h>#include <xmenu.h>#include <xerror.h>#include "ui.h"#include "ui_win32.h"#include "resource.h"#include "xio.h"#include <cursor.h>#define MAXRESOLUTIONS 256#define DXWIDTH 320#define DXHEIGHT 200#define DXBPP 8#define WWIDTH (480+4*48)#define WHEIGHT (360+4*36)#define DXFULLSCREEN 1#define DXWINDOWED 2#define MOUSEWIDTH 16#define MOUSEHEIGHT 16#ifdef HAVE_GETTEXT#include <libintl.h>#include <locale.h>#else#define gettext(STRING) STRING#endifHINSTANCE hInstance;HWND hWnd;CONST char *helptopic = "main";struct ui_driver win32_driver;struct ui_driver dxw_driver, dxf_driver;static int initialized = 0, needredraw = 0;static char *helpname = NULL;/* This variables are used by drivers in initializetion */static int windowpos;static CONST char *size = "520x430";static CONST char *dxsize = "320x200x8";/* Display information */static int displayX, displayY, bitDepth;static int lineSize;static int fontWidth, fontHeight;static HPALETTE hPalette = NULL;static char *buffer1;static char *buffer2;static int currentbuff = 0;static BITMAPINFO *bmp = NULL;/* Mouse */static int mouseX, mouseY, mouseButtons = 0;static int captured = 0, tmpcaptured = 0;/* Keyboard state */static int altPressed;static int arrowsPressed;/* WindowProc comunication variables */static BOOL closeFlag;static int resized = 0;static int active = 1;/* Curent class information */static HICON hIcon;static HICON hIconSm;static HFONT hFont = NULL;/* DirectX stuff */#ifdef DDRAW_DRIVERint directX = 0;static LPDIRECTDRAWPALETTE dxPalette = NULL;static LPDIRECTDRAW lpDD = NULL;static LPDIRECTDRAW2 lpDD2 = NULL;static LPDIRECTDRAWSURFACE lpSurfaces[2], BackSurface[2];static DDSURFACEDESC surface[2];static CONST char *mousepointer = mouse_pointer_data;static char *storeddata = NULL;static HMODULE hModule = NULL;static int oldmouseX, oldmouseY;#else#define directX 0#endifstatic PUCHAR backpalette[256][4];static HMODULE hModule2;static RECT rcWindow;static RECT rcViewport;static RECT rcScreen;static int MyHelpMsg;/*clipboard*/static WORD clipboard_format;/* forward declarations */#ifdef DDRAW_DRIVERstatic void DeInitDD (void);static void PaintDD (void);static void UpdateMouseDD (void);#endifstatic void Paint (HDC hDC);static void CalculateBITMAPINFO (void);static void win32_display (void);static void DeInitWindow (void);#ifdef DDRAW_DRIVER /* FIXME: In windowed mode we don't support 8bpp yet! */#define DXSUPPORTEDDEPTH(fullscreen,depth) \ (!(depth < 8 || (!fullscreen && depth != 16 && depth !=24 && depth != 32)))static char *store (char *data, int depth, int lpitch, int width, int height, int xpos, int ypos){ int d = depth / 8; char *store = malloc (d * MOUSEWIDTH * MOUSEHEIGHT); int y; if (xpos + MOUSEWIDTH > width) xpos = width - MOUSEWIDTH; if (ypos + MOUSEHEIGHT > height) ypos = height - MOUSEHEIGHT; if (xpos < 0) xpos = 0; if (ypos < 0) ypos = 0; for (y = 0; y < MOUSEHEIGHT; y++) memcpy (store + d * MOUSEWIDTH * y, data + xpos * d + (ypos + y) * lpitch, MOUSEWIDTH * d); return store;}static voidrestore (char *data, CONST char *store, int depth, int lpitch, int width, int height, int xpos, int ypos){ int y; int d = depth / 8; if (xpos + MOUSEWIDTH > width) xpos = width - MOUSEWIDTH; if (ypos + MOUSEHEIGHT > height) ypos = height - MOUSEHEIGHT; if (xpos < 0) xpos = 0; if (ypos < 0) ypos = 0; for (y = 0; y < MOUSEHEIGHT; y++) memcpy (data + xpos * d + (ypos + y) * lpitch, store + d * MOUSEWIDTH * y, MOUSEWIDTH * d);}static voiddrawmouse (char *data, CONST char *mouse, int depth, int lpitch, int width, int height, int xpos, int ypos){ int x, y, z, c; int d = depth / 8; for (y = 0; y < MOUSEWIDTH; y++) for (x = 0; x < MOUSEWIDTH; x++) if (mouse[x + MOUSEWIDTH * y] && x + xpos > 0 && (x + xpos) < width && y + ypos > 0 && y + ypos < height) { c = mouse[x + MOUSEWIDTH * y] == 2 ? (d == 1 ? 1 : 255) : 0; for (z = 0; z < d; z++) data[z + d * (x + xpos) + (y + ypos) * lpitch] = c; }}#endifstatic voidgetdimens (float *width, float *height){ HDC hDC = GetDC (hWnd); *width = GetDeviceCaps (hDC, HORZSIZE) / 10.0; *height = GetDeviceCaps (hDC, VERTSIZE) / 10.0; if (*width > 100 || *width < 1) *width = 29.0; if (*height > 100 || *height < 1) *height = 21.0; ReleaseDC (hWnd, hDC);}static voidgetres (float *width, float *height){ HDC hDC = GetDC (hWnd); *width = 2.54 / GetDeviceCaps (hDC, LOGPIXELSX); *height = 2.54 / GetDeviceCaps (hDC, LOGPIXELSY); ReleaseDC (hWnd, hDC);}/****************************************************************************** Win32 driver helper routines */static LRESULT CALLBACKWindowProc (HWND hWnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ){ PAINTSTRUCT paintStruct; HDC hDC; if (uMsg == (unsigned int) MyHelpMsg) { win32_help (NULL, helptopic); return 0; } switch (uMsg) { case WM_COMMAND: win32_pressed (wParam); break; case WM_SIZE: // resize window if (directX == DXFULLSCREEN) return 0; if (LOWORD (lParam) == 0 && HIWORD (lParam) == 0) { active = 0; break; } /*Minimized window */ active = 1; if (displayX != LOWORD (lParam) || displayY != HIWORD (lParam)) resized = 1; displayX = LOWORD (lParam); displayY = HIWORD (lParam); break; case WM_DISPLAYCHANGE: if (directX == DXFULLSCREEN) return 0; mouseButtons = 0; resized = 1; hDC = GetDC (hWnd); bitDepth = GetDeviceCaps (hDC, BITSPIXEL); ReleaseDC (hWnd, hDC); break; case WM_CLOSE: // close window closeFlag = TRUE; return 0; case WM_MOUSEMOVE: case WM_LBUTTONUP: case WM_LBUTTONDOWN: case WM_RBUTTONUP: case WM_RBUTTONDOWN: case WM_MBUTTONUP: case WM_MBUTTONDOWN: // handle mouse move and mouse buttons mouseButtons = wParam; if (!captured) { if (mouseButtons && !tmpcaptured) SetCapture (hWnd), tmpcaptured = 1; if (!mouseButtons && tmpcaptured) ReleaseCapture (), tmpcaptured = 0; } mouseX = (short) LOWORD (lParam); mouseY = (short) HIWORD (lParam);#ifdef DDRAW_DRIVER if (directX == DXFULLSCREEN) { POINT p; GetCursorPos (&p); mouseX = p.x; mouseY = p.y; UpdateMouseDD (); }#endif break; case WM_PAINT: // redraw screen if (directX == DXFULLSCREEN) return 0; needredraw = 1; if (GetUpdateRect (hWnd, NULL, FALSE)) { HDC hDC = BeginPaint (hWnd, &paintStruct); if (hDC) {#ifdef DDRAW_DRIVER if (directX) PaintDD (); else#endif Paint (hDC); EndPaint (hWnd, &paintStruct); } } return 0; case WM_QUERYNEWPALETTE: // windows calls this when window is reactivated. if (directX == DXFULLSCREEN) return 0; hDC = GetDC (hWnd);#ifdef DDRAW_DRIVER if (directX == DXWINDOWED) { if (dxPalette) { IDirectDrawSurface_SetPalette (lpSurfaces[0], dxPalette); IDirectDrawPalette_SetEntries (dxPalette, 0, 0, 255, (PALETTEENTRY *) backpalette); } } else#endif { SelectPalette (hDC, hPalette, FALSE); RealizePalette (hDC); } ReleaseDC (hWnd, hDC); return TRUE; case WM_MOVE: if (directX != DXFULLSCREEN) { GetWindowRect (hWnd, &rcWindow); GetClientRect (hWnd, &rcViewport); GetClientRect (hWnd, &rcScreen); ClientToScreen (hWnd, (POINT *) & rcScreen.left); ClientToScreen (hWnd, (POINT *) & rcScreen.right); } break; case WM_SETCURSOR: if (directX == DXFULLSCREEN) { SetCursor (NULL); return TRUE; } break;#ifdef DDRAW_DRIVER case WM_ACTIVATEAPP: { int oldactive = active; mouseButtons = 0; if (directX == DXFULLSCREEN) { needredraw = 1; active = (wParam == WA_ACTIVE) || (wParam == WA_CLICKACTIVE) /*(BOOL) wParam */ ; PaintDD (); if (!oldactive && active && captured) SetCursor (NULL), SetCapture (hWnd); if (oldactive && !active && captured) ReleaseCapture (); return 0L; } }#endif break; } return DefWindowProc (hWnd, uMsg, wParam, lParam);}/*Create Xaos Window. It is either used for normal window mode or as basis for DirectX */static intInitWindow (void){ int width = CW_USEDEFAULT, height = CW_USEDEFAULT; int xpos = CW_USEDEFAULT, ypos = CW_USEDEFAULT; LOGPALETTE *logPalette; WNDCLASS wndClass; LOGFONT logFont; ATOM a; HDC hDC; TEXTMETRIC textMetric; HGLOBAL oldFont; RECT r; closeFlag = FALSE; altPressed = arrowsPressed = 0; if (hIcon == NULL) hIcon = LoadIcon (hInstance, "BIG"); mouseButtons = 0; mouseX = 0; mouseY = 0; { static FARPROC proc; if (hModule2 == NULL) { hModule2 = LoadLibrary ("user32"); proc = GetProcAddress (hModule2, "RegisterClassExA"); } if (proc != NULL) { WNDCLASSEX ExWndClass; memset (&ExWndClass, 0, sizeof (WNDCLASSEX)); if (hIconSm == NULL) hIconSm = LoadIcon (hInstance, "SMALL"); ExWndClass.hIconSm = hIconSm; memset (&ExWndClass, 0, sizeof (WNDCLASSEX)); ExWndClass.style = CS_OWNDC; ExWndClass.cbSize = sizeof (WNDCLASSEX); ExWndClass.lpfnWndProc = WindowProc; ExWndClass.hInstance = hInstance; ExWndClass.hIcon = hIcon; ExWndClass.hCursor = LoadCursor (NULL, IDC_ARROW); ExWndClass.lpszClassName = "XaosWindow"; ExWndClass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH); a = (ATOM) proc (&ExWndClass); } else { memset (&wndClass, 0, sizeof (WNDCLASS)); wndClass.style = CS_OWNDC; wndClass.lpfnWndProc = WindowProc; wndClass.hInstance = hInstance; wndClass.hIcon = hIcon; wndClass.hCursor = LoadCursor (NULL, IDC_ARROW); wndClass.lpszClassName = "XaosWindow"; wndClass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH); a = RegisterClass (&wndClass); } } if (!a) { x_error ("Unable to create windows class"); return 0; } /* First time use defaut size, otherwise use saved sizes */ if (sscanf (size, "%ix%ix", &width, &height) != 2) { width = WWIDTH; height = WHEIGHT; } if (windowpos) { xpos = rcWindow.left; ypos = rcWindow.top; width = rcWindow.right - rcWindow.left; height = rcWindow.bottom - rcWindow.top; } /* create main window */ if (directX == DXFULLSCREEN) hWnd = CreateWindowEx (WS_EX_TOPMOST, "XaoSWindow", "XaoS", WS_POPUP, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), NULL, NULL, hInstance, NULL); else hWnd = CreateWindowEx (WS_EX_CLIENTEDGE, "XaoSWindow", "XaoS", WS_OVERLAPPEDWINDOW | WS_EX_LEFTSCROLLBAR, xpos, ypos, width, height, NULL, NULL, hInstance, NULL); if (!hWnd) { x_error ("Unable to create app window"); return 0; } clipboard_format = RegisterClipboardFormat ("image/x-xaos.position"); /* create font */ memset (&logFont, 0, sizeof (LOGFONT)); hDC = CreateDC ("DISPLAY", NULL, NULL, NULL); logFont.lfHeight = -MulDiv (12, GetDeviceCaps (hDC, LOGPIXELSY), 72); logFont.lfWeight = FW_NORMAL; logFont.lfPitchAndFamily = FIXED_PITCH; strcpy (logFont.lfFaceName, "Courier"); hFont = CreateFontIndirect (&logFont); oldFont = SelectObject (hDC, hFont); GetTextMetrics (hDC, &textMetric); SelectObject (hDC, oldFont); DeleteDC (hDC); fontHeight = textMetric.tmHeight; fontWidth = textMetric.tmAveCharWidth; ShowWindow (hWnd, SW_NORMAL); GetClientRect (hWnd, &r); displayX = r.right; displayY = r.bottom; /* create palette */ CalculateBITMAPINFO (); /* calculate BITMAPINFO structure */ logPalette = malloc (sizeof (LOGPALETTE) + 4 * 256); logPalette->palVersion = 0x300; logPalette->palNumEntries = 256; memcpy (logPalette->palPalEntry, bmp->bmiColors, 4 * 256); hPalette = CreatePalette (logPalette); free (logPalette); /* select and realize palette */ hDC = GetDC (hWnd); SelectPalette (hDC, hPalette, FALSE); RealizePalette (hDC); ReleaseDC (hWnd, hDC); // increase priority of XaoS SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_ABOVE_NORMAL); MyHelpMsg = RegisterWindowMessage (HELPMSGSTRING); return 1;}static voidDeInitWindow (){ if (tmpcaptured) ReleaseCapture (); if (directX != DXFULLSCREEN) windowpos = 1, GetWindowRect (hWnd, &rcWindow); /* normalize priority */ SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL); if (helpname) WinHelp (hWnd, helpname, HELP_QUIT, 0), free (helpname), helpname = NULL; /* destroy windows and other objects */ DeleteObject (hFont); DestroyWindow (hWnd); UnregisterClass ("XaosWindow", hInstance); if (bmp) { free (bmp); bmp = NULL; } if (hModule2 != NULL) FreeLibrary (hModule2); hModule2 = NULL; win32_uninitializewindows ();}/* Display buffer to screen */static voidPaint (HDC hDC){ if (!initialized || !buffer1) return; StretchDIBits (hDC, 0, 0, displayX, displayY, 0, 0, displayX, displayY, (currentbuff == 0) ? buffer1 : buffer2, bmp, DIB_RGB_COLORS, SRCCOPY); needredraw = 0;}static intInit (void){ HDC hDC; buffer1 = buffer2 = NULL; // get bit depth hDC = CreateDC ("DISPLAY", NULL, NULL, NULL); bitDepth = GetDeviceCaps (hDC, BITSPIXEL); if (bitDepth < 8) bitDepth = 16; if (bitDepth < 10) bitDepth = 8; if (bitDepth >= 10 && bitDepth < 20) bitDepth = 16; if (bitDepth >= 20 && bitDepth < 28) bitDepth = 24; if (bitDepth >= 32 && bitDepth < 32) bitDepth = 32; DeleteDC (hDC); // create windows and other objects if (!InitWindow ()) return 0; CalculateBITMAPINFO (); /* calculate BITMAPINFO structure */ return 1;}static voidgetmouse (int *mx, int *my, int *mb){ *mb = 0; if (mouseButtons & MK_LBUTTON) *mb |= 256; if (mouseButtons & MK_MBUTTON) *mb |= 512; if (mouseButtons & MK_RBUTTON) *mb |= 1024; *mx = mouseX; *my = mouseY;}static voidProcessevents (int wait, int *mx, int *my, int *mb, int *k, int *c){ MSG msg; int r; if (wait) { // wait for message if in wait mode r = GetMessage (&msg, hWnd, 0, 0); wait = 0; } else { // don't wait for message r = PeekMessage (&msg, hWnd, 0, 0, PM_REMOVE); }#if 0 if (needredraw) { if (directX) PaintDD (); else win32_display (); }#endif if (r > 0) { if (msg.message == WM_CHAR) { // ascii char *c = msg.wParam; } if (msg.message == WM_KEYUP) switch (msg.wParam) { case VK_MENU: altPressed = 0; break; case VK_UP: arrowsPressed &= ~4; break; case VK_DOWN: arrowsPressed &= ~8; break; case VK_LEFT: arrowsPressed &= ~1; break; case VK_RIGHT: arrowsPressed &= ~2; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -