⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winuser.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 + -