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

📄 message.c

📁 在ADS环境下MiniGUI的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
** $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 + -