📄 message.c
字号:
/*
** $Id: message.c,v 1.21 2004/06/26 07:49:32 weiym Exp $
**
** message.c: The Messaging module.
**
** Copyright (C) 2003 Feynman Software.
** Copyright (C) 2000 ~ 2002 Wei Yongming.
**
** Current maintainer: Wei Yongming.
**
** Create date: 2000/11/05
*/
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
** TODO:
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "blockheap.h"
#include "cliprect.h"
#include "gal.h"
#include "internals.h"
#include "ctrlclass.h"
#include "timer.h"
/****************************** Message support ******************************/
static BLOCKHEAP QMSGHeap;
/* QMSG allocation */
BOOL InitFreeQMSGList (void)
{
InitBlockDataHeap (&QMSGHeap, sizeof (QMSG), SIZE_QMSG_HEAP);
return TRUE;
}
void DestroyFreeQMSGList (void)
{
DestroyBlockDataHeap (&QMSGHeap);
}
inline static PQMSG QMSGAlloc (void)
{
return (PQMSG) BlockDataAlloc (&QMSGHeap);
}
inline static void FreeQMSG (PQMSG pqmsg)
{
BlockDataFree (&QMSGHeap, pqmsg);
}
BOOL InitMsgQueue (PMSGQUEUE pMsgQueue, int iBufferLen)
{
int i;
pMsgQueue->dwState = QS_EMPTY;
#ifndef _LITE_VERSION
pthread_mutex_init (&pMsgQueue->lock, NULL);
sem_init (&pMsgQueue->wait, 0, 0);
#endif
pMsgQueue->pFirstNotifyMsg = NULL;
pMsgQueue->pLastNotifyMsg = NULL;
pMsgQueue->readpos = 0;
pMsgQueue->writepos = 0;
#ifndef _LITE_VERSION
pMsgQueue->pFirstSyncMsg = NULL;
pMsgQueue->pLastSyncMsg = NULL;
#endif
if (iBufferLen <= 0)
iBufferLen = DEF_MSGQUEUE_LEN;
pMsgQueue->msg = malloc (sizeof (MSG) * iBufferLen);
pMsgQueue->len = iBufferLen;
#ifndef _LITE_VERSION
pMsgQueue->TimerMask = 0xFF;
#else
pMsgQueue->TimerMask = 0xFFFF;
#endif
for (i = 0; i < DEF_NR_TIMERS; i++) {
pMsgQueue->TimerOwner [i] = HWND_DESKTOP;
pMsgQueue->TimerID [i] = 0;
}
return pMsgQueue->msg != NULL;
}
void DestroyMsgQueue (PMSGQUEUE pMsgQueue)
{
PQMSG head;
PQMSG next;
head = next = pMsgQueue->pFirstNotifyMsg;
while (head) {
next = head->next;
FreeQMSG (head);
head = next;
}
#ifndef _LITE_VERSION
pthread_mutex_destroy (&pMsgQueue->lock);
sem_destroy (&pMsgQueue->wait);
#endif
free (pMsgQueue->msg);
pMsgQueue->msg = NULL;
}
#ifdef _LITE_VERSION
BOOL InitDskMsgQueue (void)
{
return InitMsgQueue (&__mg_dsk_msgs, 0);
}
void DestroyDskMsgQueue (void)
{
DestroyMsgQueue (&__mg_dsk_msgs);
}
#endif
PMAINWIN CheckAndGetMainWindowPtr (HWND hWnd)
{
PMAINWIN pWin;
pWin = (PMAINWIN)hWnd;
if(pWin->DataType != TYPE_HWND)
return NULL;
if (pWin->WinType == TYPE_MAINWIN)
return pWin;
return NULL;
}
PMAINWIN GetMainWindowPtrOfControl (HWND hWnd)
{
PMAINWIN pWin;
if (hWnd == HWND_DESKTOP || hWnd == HWND_INVALID)
return NULL;
pWin = (PMAINWIN)hWnd;
if(pWin->DataType != TYPE_HWND)
return NULL;
if (pWin->WinType == TYPE_MAINWIN)
return pWin;
return ((PCONTROL)hWnd)->pMainWin;
}
PMSGQUEUE GetMsgQueue (HWND hWnd)
{
if (hWnd == HWND_DESKTOP) return &__mg_dsk_msgs;
return GetMainWindowPtrOfControl (hWnd)->pMessages;
}
static inline WNDPROC GetWndProc (HWND hWnd)
{
PMAINWIN pMainWin = (PMAINWIN)hWnd;
if (hWnd == HWND_DESKTOP)
return DesktopWinProc;
return pMainWin->MainWindowProc;
}
static HWND msgCheckInvalidRegion (PMAINWIN pWin)
{
PCONTROL pCtrl = (PCONTROL)pWin;
HWND hwnd;
if (pCtrl->InvRgn.rgn.head)
return (HWND)pCtrl;
pCtrl = pCtrl->children;
while (pCtrl) {
if ((hwnd = msgCheckInvalidRegion ((PMAINWIN) pCtrl)))
return hwnd;
pCtrl = pCtrl->next;
}
return 0;
}
static PMAINWIN msgGetHostingRoot (PMAINWIN pHosted)
{
PMAINWIN pHosting;
pHosting = pHosted->pHosting;
if (pHosting)
return msgGetHostingRoot (pHosting);
return pHosted;
}
static HWND msgCheckHostedTree (PMAINWIN pHosting)
{
HWND hNeedPaint;
PMAINWIN pHosted;
if ( (hNeedPaint = msgCheckInvalidRegion (pHosting)) )
return hNeedPaint;
pHosted = pHosting->pFirstHosted;
while (pHosted) {
if ( (hNeedPaint = msgCheckHostedTree (pHosted)) )
return hNeedPaint;
pHosted = pHosted->pNextHosted;
}
return 0;
}
static void CheckCapturedMouseMessage (PMSG pMsg)
{
if (pMsg->message >= MSG_FIRSTMOUSEMSG
&& pMsg->message <= MSG_LASTMOUSEMSG) {
#ifndef _LITE_VERSION
if (__mg_capture_wnd && (__mg_capture_wnd != HWND_INVALID)
&& (GetMsgQueue (__mg_capture_wnd) == GetMsgQueue (pMsg->hwnd))) {
#else
if (__mg_capture_wnd && (__mg_capture_wnd != HWND_INVALID)
&& pMsg->hwnd != HWND_DESKTOP) {
#endif
if (!(pMsg->wParam | KS_CAPTURED)) {
int x, y;
x = LOSWORD (pMsg->lParam);
y = HISWORD (pMsg->lParam);
ClientToScreen (pMsg->hwnd, &x, &y);
pMsg->lParam = MAKELONG (x, y);
pMsg->wParam |= KS_CAPTURED;
}
pMsg->hwnd = __mg_capture_wnd;
}
}
}
BOOL GUIAPI HavePendingMessage (HWND hWnd)
{
PMSGQUEUE pMsgQueue;
if( !(pMsgQueue = GetMsgQueue(hWnd)) ) return FALSE;
if (pMsgQueue->dwState & QS_NOTIFYMSG) {
if (pMsgQueue->pFirstNotifyMsg)
return TRUE;
}
#ifndef _LITE_VERSION
if (pMsgQueue->dwState & QS_SYNCMSG) {
if (pMsgQueue->pFirstSyncMsg)
return TRUE;
}
#endif
if (pMsgQueue->dwState & QS_POSTMSG) {
if (pMsgQueue->readpos != pMsgQueue->writepos)
return TRUE;
}
#ifndef _LITE_VERSION
if (pMsgQueue->dwState & (QS_QUIT | QS_PAINT | QS_TIMER))
#else
if (pMsgQueue->dwState & (QS_QUIT | QS_PAINT | QS_TIMER | QS_DESKTIMER))
#endif
return TRUE;
#ifdef _LITE_VERSION
return pMsgQueue->OnIdle (NULL);
#else
return FALSE;
#endif
}
int GUIAPI BroadcastMessage (int iMsg, WPARAM wParam, LPARAM lParam)
{
MSG msg;
msg.message = iMsg;
msg.wParam = wParam;
msg.lParam = lParam;
return SendMessage (HWND_DESKTOP, MSG_BROADCASTMSG, 0, (LPARAM)(&msg));
}
#ifdef _MSG_STRING
#include "msgstr.h"
const char* GUIAPI Message2Str (int message)
{
if (message >= 0x0000 && message <= 0x006F)
return msgstr1 [message];
else if (message >= 0x00A0 && message <= 0x010F)
return msgstr2 [message - 0x00A0];
else if (message >= 0x0120 && message <= 0x017F)
return msgstr3 [message - 0x0120];
else if (message >= 0xF000)
return "Control Messages";
else
return "MSG_USER";
}
void GUIAPI PrintMessage (FILE* fp, HWND hWnd, int iMsg, WPARAM wParam, LPARAM lParam)
{
fprintf (fp, "Message %s: hWnd: %#x, wP: %x, lP: %lx.\n",
Message2Str (iMsg), hWnd, wParam, lParam);
}
#endif
#ifdef _LITE_VERSION
int GUIAPI GetMessage (PMSG pMsg, HWND hWnd)
{
PMSGQUEUE pMsgQueue;
PQMSG phead;
int slot;
if( !(pMsgQueue = GetMsgQueue(hWnd)) ) return ERR_INV_HWND;
memset (pMsg, 0, sizeof(MSG));
checkagain:
if (pMsgQueue->dwState & QS_QUIT) {
pMsg->hwnd = hWnd;
pMsg->message = MSG_QUIT;
pMsg->wParam = 0;
pMsg->lParam = 0;
pMsgQueue->dwState &= ~QS_QUIT;
return 0;
}
if (pMsgQueue->dwState & QS_NOTIFYMSG) {
if (pMsgQueue->pFirstNotifyMsg) {
phead = pMsgQueue->pFirstNotifyMsg;
pMsgQueue->pFirstNotifyMsg = phead->next;
*pMsg = phead->Msg;
FreeQMSG (phead);
return 1;
}
else
pMsgQueue->dwState &= ~QS_NOTIFYMSG;
}
if (pMsgQueue->dwState & QS_POSTMSG) {
if (pMsgQueue->readpos != pMsgQueue->writepos) {
*pMsg = pMsgQueue->msg[pMsgQueue->readpos];
CheckCapturedMouseMessage (pMsg);
pMsgQueue->readpos++;
if (pMsgQueue->readpos >= pMsgQueue->len) pMsgQueue->readpos = 0;
return 1;
}
else
pMsgQueue->dwState &= ~QS_POSTMSG;
}
if (pMsgQueue->dwState & QS_PAINT) {
PMAINWIN pHostingRoot;
HWND hNeedPaint;
PMAINWIN pWin;
if (hWnd == HWND_DESKTOP) {
pMsg->hwnd = hWnd;
pMsg->message = MSG_PAINT;
pMsg->wParam = 0;
pMsg->lParam = 0;
pMsgQueue->dwState &= ~QS_PAINT;
return 1;
}
pMsg->message = MSG_PAINT;
pMsg->wParam = 0;
pMsg->lParam = 0;
pWin = GetMainWindowPtrOfControl (hWnd);
pHostingRoot = msgGetHostingRoot (pWin);
if ( (hNeedPaint = msgCheckHostedTree (pHostingRoot)) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -