📄 winuser.c
字号:
/*
* Copyright (c) 1999 Greg Haerr <greg@censoft.com>
*
* Win32 API upper level window creation, management and msg routines
*/
#include "windows.h"
#include "wintern.h"
#include "device.h"
#include <stdlib.h>
#include <string.h>
#define PAINTONCE 1 /* =1 to queue paint msgs only once*/
#define MOUSETEST 1
MWLISTHEAD mwMsgHead; /* application msg queue*/
MWLISTHEAD mwClassHead; /* register class list*/
int mwSYSMETRICS_CYCAPTION = 12; /* Y caption height*/
int mwSYSMETRICS_CXFRAME = 3; /* width of frame border*/
int mwSYSMETRICS_CYFRAME = 3; /* height of frame border*/
int mwSYSMETRICS_CXBORDER = 1; /* width of single border*/
int mwSYSMETRICS_CYBORDER = 1; /* width of single border*/
int mwSYSMETRICS_CXVSCROLL = 13; /* width of vertical scrollbar*/
int mwSYSMETRICS_CYHSCROLL = 13; /* height of horizontal scrollbar*/
int mwSYSMETRICS_CXHSCROLL = 13; /* width of arrow on horz scrollbar*/
int mwSYSMETRICS_CYVSCROLL = 13; /* height of arrow on vert scrollbar*/
int mwSYSMETRICS_CXDOUBLECLK = 2; /* +/- X double click position*/
int mwSYSMETRICS_CYDOUBLECLK = 2; /* +/- Y double click position*/
int mwpaintSerial = 1; /* experimental alphablend sequencing*/
int mwpaintNC = 1; /* experimental NC paint handling*/
BOOL mwforceNCpaint = FALSE; /* force NC paint when alpha blending*/
static void MwOffsetChildren(HWND hwnd, int offx, int offy);
LRESULT WINAPI
CallWindowProc(WNDPROC lpPrevWndFunc, HWND hwnd, UINT Msg, WPARAM wParam,
LPARAM lParam)
{
return (*lpPrevWndFunc)(hwnd, Msg, wParam, lParam);
}
LRESULT WINAPI
SendMessage(HWND hwnd, UINT Msg,WPARAM wParam,LPARAM lParam)
{
if(hwnd && hwnd->pClass) {
hwnd->paintSerial = mwpaintSerial; /* assign msg sequence #*/
return (*hwnd->pClass->lpfnWndProc)(hwnd, Msg, wParam, lParam);
}
return 0;
}
BOOL WINAPI
PostMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
MSG * pMsg;
#if PAINTONCE
/* don't queue paint msgs, set window paint status instead*/
if(Msg == WM_PAINT) {
hwnd->gotPaintMsg = PAINT_NEEDSPAINT;
return TRUE;
}
#endif
#if MOUSETEST
/* replace multiple mouse messages with one for better mouse handling*/
if(Msg == WM_MOUSEMOVE) {
PMWLIST p;
for(p=mwMsgHead.head; p; p=p->next) {
pMsg = GdItemAddr(p, MSG, link);
if(pMsg->hwnd == hwnd && pMsg->message == Msg) {
pMsg->wParam = wParam;
pMsg->lParam = lParam;
pMsg->time = GetTickCount();
pMsg->pt.x = cursorx;
pMsg->pt.y = cursory;
return TRUE;
}
}
}
#endif
pMsg = GdItemNew(MSG);
if(!pMsg)
return FALSE;
pMsg->hwnd = hwnd;
pMsg->message = Msg;
pMsg->wParam = wParam;
pMsg->lParam = lParam;
pMsg->time = GetTickCount();
pMsg->pt.x = cursorx;
pMsg->pt.y = cursory;
GdListAdd(&mwMsgHead, &pMsg->link);
return TRUE;
}
/* currently, we post to the single message queue, regardless of thread*/
BOOL WINAPI
PostThreadMessage(DWORD dwThreadId, UINT Msg, WPARAM wParam, LPARAM lParam)
{
return PostMessage(NULL, Msg, wParam, lParam);
}
VOID WINAPI
PostQuitMessage(int nExitCode)
{
PostMessage(NULL, WM_QUIT, nExitCode, 0L);
}
static BOOL
chkPaintMsg(HWND wp, LPMSG lpMsg)
{
/*
* Tricky: only repaint window if there
* isn't a mouse capture (window move) in progress,
* or the window is the moving window.
*/
if(wp->gotPaintMsg == PAINT_NEEDSPAINT &&
(!dragwp || dragwp == wp)) {
paint:
wp->gotPaintMsg = PAINT_PAINTED;
lpMsg->hwnd = wp;
lpMsg->message = WM_PAINT;
lpMsg->wParam = 0;
lpMsg->lParam = 0;
lpMsg->time = 0;
lpMsg->pt.x = cursorx;
lpMsg->pt.y = cursory;
return TRUE;
} else if(dragwp && wp->gotPaintMsg == PAINT_NEEDSPAINT) {
/* All other windows we'll check for
* event input first, then allow repaint.
*/
MwSelect();
if(mwMsgHead.head == NULL)
goto paint;
}
return FALSE;
}
BOOL WINAPI
PeekMessage(LPMSG lpMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax,
UINT wRemoveMsg)
{
HWND wp;
PMSG pNxtMsg;
/* check if no messages in queue*/
if(mwMsgHead.head == NULL) {
#if PAINTONCE
/* check all windows for pending paint messages*/
for(wp=listwp; wp; wp=wp->next) {
if(!(wp->style & WS_CHILD)) {
if(chkPaintMsg(wp, lpMsg))
return TRUE;
}
}
for(wp=listwp; wp; wp=wp->next) {
if(wp->style & WS_CHILD) {
if(chkPaintMsg(wp, lpMsg))
return TRUE;
}
}
#endif
MwSelect();
}
if(mwMsgHead.head == NULL)
return FALSE;
pNxtMsg = (PMSG)mwMsgHead.head;
if(wRemoveMsg & PM_REMOVE)
GdListRemove(&mwMsgHead, &pNxtMsg->link);
*lpMsg = *pNxtMsg;
if(wRemoveMsg & PM_REMOVE)
GdItemFree(pNxtMsg);
return TRUE;
}
BOOL WINAPI
GetMessage(LPMSG lpMsg,HWND hwnd,UINT wMsgFilterMin,UINT wMsgFilterMax)
{
/*
* currently MwSelect() must poll for VT switch reasons,
* so this code will work
*/
while(!PeekMessage(lpMsg, hwnd, wMsgFilterMin, wMsgFilterMax,PM_REMOVE))
continue;
return lpMsg->message != WM_QUIT;
}
BOOL WINAPI
TranslateMessage(CONST MSG *lpMsg)
{
return FALSE;
}
LONG WINAPI
DispatchMessage(CONST MSG *lpMsg)
{
return SendMessage(lpMsg->hwnd, lpMsg->message, lpMsg->wParam,
lpMsg->lParam);
}
/* find the registered window class struct by name*/
PWNDCLASS
MwFindClassByName(LPCSTR lpClassName)
{
PMWLIST p;
PWNDCLASS pClass;
for(p=mwClassHead.head; p; p=p->next) {
pClass = GdItemAddr(p, WNDCLASS, link);
if(strcmpi(pClass->szClassName, lpClassName) == 0)
return pClass;
}
return NULL;
}
ATOM WINAPI
RegisterClass(CONST WNDCLASS *lpWndClass)
{
PWNDCLASS pClass;
/* check if already present*/
pClass = MwFindClassByName(lpWndClass->lpszClassName);
if(pClass)
return 0;
/* copy class into new struct*/
pClass = GdItemNew(WNDCLASS);
if(!pClass)
return 0;
*pClass = *lpWndClass;
strcpy(pClass->szClassName, lpWndClass->lpszClassName);
GdListAdd(&mwClassHead, &pClass->link);
return 1;
}
BOOL WINAPI
UnregisterClass(LPCSTR lpClassName, HINSTANCE hInstance)
{
PWNDCLASS pClass;
pClass = MwFindClassByName(lpClassName);
if(!pClass)
return FALSE;
GdListRemove(&mwClassHead, &pClass->link);
DeleteObject(pClass->hbrBackground);
GdItemFree(pClass);
return TRUE;
}
HWND WINAPI
CreateWindowEx(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName,
DWORD dwStyle, int x, int y, int nWidth, int nHeight,
HWND hwndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
HWND pwp; /* parent window */
HWND wp; /* new window */
HWND hwndOwner;
PWNDCLASS pClass;
CREATESTRUCT cs;
static int nextx = 20;
static int nexty = 20;
pClass = MwFindClassByName(lpClassName);
if(!pClass)
return NULL;
if(x == CW_USEDEFAULT || y == CW_USEDEFAULT) {
x = nextx;
nextx += 10;
y = nexty;
nexty += 10;
if(nextx > 200)
nextx = nexty = 20;
}
if(nWidth == CW_USEDEFAULT || nHeight == CW_USEDEFAULT) {
nWidth = 250;
nHeight = 250;
}
if(hwndParent == NULL) {
if(dwStyle & WS_CHILD)
return NULL;
pwp = rootwp;
} else
pwp = hwndParent;
/* WS_POPUP z-order parent is the root window (passed parent is owner)*/
if(dwStyle & WS_POPUP)
pwp = rootwp; /* force clip to root, not z-parent*/
/* window owner is NULL for child windows, else it's the passed parent*/
if(dwStyle & WS_CHILD)
hwndOwner = NULL;
else hwndOwner = hwndParent;
wp = (HWND)GdItemAlloc(sizeof(struct hwnd) - 1 + pClass->cbWndExtra);
if(!wp)
return NULL;
/* force all clipping on by default*/
dwStyle |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
wp->pClass = pClass;
wp->style = dwStyle;
wp->exstyle = dwExStyle;
wp->parent = pwp;
wp->owner = hwndOwner;
wp->children = NULL;
wp->siblings = pwp->children;
pwp->children = wp;
wp->next = listwp;
listwp = wp;
wp->winrect.left = pwp->clirect.left + x;
wp->winrect.top = pwp->clirect.top + y;
wp->winrect.right = wp->winrect.left + nWidth;
wp->winrect.bottom = wp->winrect.top + nHeight;
wp->cursor = pwp->cursor;
wp->cursor->usecount++;
wp->unmapcount = pwp->unmapcount + 1;
wp->id = (int)hMenu;
wp->gotPaintMsg = PAINT_PAINTED;
strzcpy(wp->szTitle, lpWindowName, sizeof(wp->szTitle));
#if UPDATEREGIONS
wp->update = GdAllocRegion();
#endif
wp->nextrabytes = pClass->cbWndExtra;
/* calculate client area*/
MwCalcClientRect(wp);
cs.lpCreateParams = lpParam;
cs.hInstance = hInstance;
cs.hMenu = hMenu;
cs.hwndParent = hwndParent;
cs.cy = nHeight;
cs.cx = nWidth;
cs.y = y;
cs.x = x;
cs.style = dwStyle;
cs.lpszName = lpWindowName;
cs.lpszClass = lpClassName;
cs.dwExStyle = dwExStyle;
if(SendMessage(wp, WM_CREATE, 0, (LPARAM)(LPSTR)&cs) == -1) {
MwDestroyWindow(wp, FALSE);
return NULL;
}
/* send SIZE and MOVE msgs*/
MwSendSizeMove(wp, TRUE, TRUE);
if(wp->style & WS_VISIBLE) {
MwShowWindow(wp, TRUE);
SetFocus(wp);
}
return wp;
}
BOOL WINAPI
DestroyWindow(HWND hwnd)
{
MwDestroyWindow(hwnd, TRUE);
return TRUE;
}
/*
* Destroy the specified window, and all of its children.
* This is a recursive routine.
*/
void
MwDestroyWindow(HWND hwnd,BOOL bSendMsg)
{
HWND wp = hwnd;
HWND prevwp;
PMWLIST p;
PMSG pmsg;
if (wp == rootwp)
return;
/*
* Unmap the window.
*/
if (wp->unmapcount == 0)
MwHideWindow(wp, FALSE, FALSE);
if(bSendMsg)
SendMessage(hwnd, WM_DESTROY, 0, 0L);
/*
* Disable all sendmessages to this window.
*/
wp->pClass = NULL;
/*
* Destroy all children, sending WM_DESTROY messages.
*/
while (wp->children)
MwDestroyWindow(wp->children, bSendMsg);
/*
* Free any cursor associated with the window.
*/
if (wp->cursor->usecount-- == 1) {
free(wp->cursor);
wp->cursor = NULL;
}
/*
* Remove this window from the child list of its parent.
*/
prevwp = wp->parent->children;
if (prevwp == wp)
wp->parent->children = wp->siblings;
else {
while (prevwp->siblings != wp)
prevwp = prevwp->siblings;
prevwp->siblings = wp->siblings;
}
wp->siblings = NULL;
/*
* Remove this window from the complete list of windows.
*/
prevwp = listwp;
if (prevwp == wp)
listwp = wp->next;
else {
while (prevwp->next != wp)
prevwp = prevwp->next;
prevwp->next = wp->next;
}
wp->next = NULL;
/*
* Forget various information related to this window.
* Then finally free the structure.
*/
/* Remove all messages from msg queue for this window*/
for(p=mwMsgHead.head; p; ) {
pmsg = GdItemAddr(p, MSG, link);
if(pmsg->hwnd == wp) {
p = p->next;
GdListRemove(&mwMsgHead, &pmsg->link);
GdItemFree(p);
} else
p = p->next;
}
/* FIXME: destroy hdc's relating to window?*/
if (wp == capturewp) {
capturewp = NULL;
MwCheckMouseWindow();
}
if (wp == MwGetTopWindow(focuswp))
SetFocus(rootwp->children? rootwp->children: rootwp);
/* destroy private DC*/
if(wp->owndc) {
HDC hdc = wp->owndc;
wp->owndc = NULL; /* force destroy with ReleaseDC*/
ReleaseDC(wp, hdc);
}
#if UPDATEREGIONS
GdDestroyRegion(wp->update);
#endif
GdItemFree(wp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -