mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-02-08 11:52:02 +08:00
6448 lines
182 KiB
C
6448 lines
182 KiB
C
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IMPORTANT NOTICE
|
|
//
|
|
// The following open source license statement does not apply to any
|
|
// entity in the Exception List published by FMSoft.
|
|
//
|
|
// For more information, please visit:
|
|
//
|
|
// https://www.fmsoft.cn/exception-list
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
* This file is part of MiniGUI, a mature cross-platform windowing
|
|
* and Graphics User Interface (GUI) support system for embedded systems
|
|
* and smart IoT devices.
|
|
*
|
|
* Copyright (C) 2002~2020, Beijing FMSoft Technologies Co., Ltd.
|
|
* Copyright (C) 1998~2002, WEI Yongming
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Or,
|
|
*
|
|
* As this program is a library, any link to this program must follow
|
|
* GNU General Public License version 3 (GPLv3). If you cannot accept
|
|
* GPLv3, you need to be licensed from FMSoft.
|
|
*
|
|
* If you have got a commercial license of this program, please use it
|
|
* under the terms and conditions of the commercial license.
|
|
*
|
|
* For more information about the commercial license, please refer to
|
|
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
|
|
*/
|
|
/*
|
|
** window.c: The Window module.
|
|
**
|
|
** Create date: 1999.04.19
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "common.h"
|
|
#include "minigui.h"
|
|
#include "gdi.h"
|
|
#include "window.h"
|
|
#include "control.h"
|
|
#include "cliprect.h"
|
|
#include "gal.h"
|
|
#include "internals.h"
|
|
#include "menu.h"
|
|
#include "ctrlclass.h"
|
|
#include "element.h"
|
|
#include "dc.h"
|
|
#ifdef _MGRM_PROCESSES
|
|
#include "client.h"
|
|
#endif
|
|
|
|
#include "license.h"
|
|
#ifdef _MG_ENABLE_LICENSE
|
|
# include "../sysres/license/c_files/04_progressbar-bk.dat.c"
|
|
#endif
|
|
#ifndef __TARGET_UNKNOWN__
|
|
unsigned int g_license_processor_id;
|
|
#endif
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
/* function defined in menu module. */
|
|
void DrawMenuBarHelper (const MAINWIN *pWin, HDC hdc, const RECT* pClipRect);
|
|
#endif
|
|
|
|
/* functions defined in caret module. */
|
|
BOOL BlinkCaret (HWND hWnd);
|
|
void GetCaretBitmaps (PCARETINFO pCaretInfo);
|
|
|
|
static void RecalcScrollInfo (PMAINWIN pWin, BOOL bIsHBar);
|
|
/* this message will auto-repeat when MSG_IDLE received */
|
|
static MSG sg_repeat_msg = {0, 0, 0, 0};
|
|
|
|
void GUIAPI SetAutoRepeatMessage (HWND hwnd, UINT msg,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hwnd;
|
|
|
|
/* if hwnd is zero, disable repeate message */
|
|
if (hwnd == 0) {
|
|
sg_repeat_msg.hwnd = 0;
|
|
sg_repeat_msg.message = 0;
|
|
sg_repeat_msg.wParam = 0;
|
|
sg_repeat_msg.lParam = 0;
|
|
return;
|
|
}
|
|
else if (hwnd == HWND_INVALID || pWin->DataType != TYPE_HWND)
|
|
return;
|
|
|
|
sg_repeat_msg.hwnd = hwnd;
|
|
sg_repeat_msg.message = msg;
|
|
sg_repeat_msg.wParam = wParam;
|
|
sg_repeat_msg.lParam = lParam;
|
|
}
|
|
|
|
static void RecalcClientArea (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hWnd;
|
|
RECT rcWin, rcClient;
|
|
int win_w, win_h, dc_w, dc_h;
|
|
PDC secondary_pdc;
|
|
|
|
memcpy (&rcWin, &pWin->left, sizeof (RECT));
|
|
memcpy (&rcClient, &pWin->cl, sizeof (RECT));
|
|
|
|
if (SendAsyncMessage (hWnd, MSG_SIZECHANGED,
|
|
(WPARAM)&rcWin, (LPARAM)&rcClient))
|
|
memcpy (&pWin->cl, &rcClient, sizeof(RECT));
|
|
|
|
if ((pWin->WinType == TYPE_MAINWIN) && pWin->secondaryDC) {
|
|
win_w = RECTWP((const RECT*)&pWin->left);
|
|
win_h = RECTHP((const RECT*)&pWin->left);
|
|
secondary_pdc = dc_HDC2PDC (pWin->secondaryDC);
|
|
dc_w = RECTW (secondary_pdc->DevRC);
|
|
dc_h = RECTH (secondary_pdc->DevRC);
|
|
|
|
if ((win_w > dc_w) || (win_h > dc_h)) {
|
|
DeleteSecondaryDC (hWnd);
|
|
pWin->secondaryDC = CreateSecondaryDC ((HWND)pWin);
|
|
|
|
if (pWin->secondaryDC == HDC_INVALID) {
|
|
/* remove the flag of WS_EX_AUTOSECONDARYDC */
|
|
pWin->dwExStyle = pWin->dwExStyle | WS_EX_AUTOSECONDARYDC;
|
|
pWin->secondaryDC = 0;
|
|
}
|
|
|
|
/* update the privCDC of pWin and child window. */
|
|
if (pWin->dwExStyle & WS_EX_USEPRIVATECDC) {
|
|
PCONTROL pNext;
|
|
PCONTROL pCtrl = (PCONTROL)(pWin->hFirstChild);
|
|
while (pCtrl) {
|
|
pNext = pCtrl->next;
|
|
if (pCtrl->dwExStyle & WS_EX_USEPRIVATECDC) {
|
|
ReleaseSecondarySubDC (pCtrl->privCDC);
|
|
pCtrl->privCDC = GetSecondarySubDC (pWin->secondaryDC,
|
|
(HWND)pCtrl, TRUE);
|
|
}
|
|
pCtrl = pNext;
|
|
}
|
|
ReleaseSecondarySubDC (pWin->privCDC);
|
|
pWin->privCDC = GetSecondarySubDC (pWin->secondaryDC,
|
|
(HWND)pWin, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
SendNotifyMessage (hWnd, MSG_CSIZECHANGED,
|
|
pWin->cr - pWin->cl, pWin->cb - pWin->ct);
|
|
}
|
|
|
|
static PCONTROL wndMouseInWhichControl (PMAINWIN pWin, int x, int y,
|
|
int* UndHitCode)
|
|
{
|
|
PCONTROL pCtrl;
|
|
int hitcode;
|
|
RECT rect;
|
|
unsigned short idx;
|
|
MASKRECT *maskrect;
|
|
|
|
pCtrl = (PCONTROL)pWin->hPrimitive;
|
|
if (pCtrl) {
|
|
if (pCtrl->primitive) {
|
|
if (UndHitCode)
|
|
*UndHitCode = HT_CLIENT;
|
|
return pCtrl;
|
|
}
|
|
else {
|
|
hitcode = SendAsyncMessage ((HWND)pCtrl, MSG_HITTEST,
|
|
(WPARAM)x, (LPARAM)y);
|
|
if (hitcode != HT_OUT && hitcode != HT_TRANSPARENT) {
|
|
if (UndHitCode)
|
|
*UndHitCode = hitcode;
|
|
return pCtrl;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (pCtrl = (PCONTROL)(pWin->hFirstChild); pCtrl && pCtrl->next; pCtrl = pCtrl->next);
|
|
while (pCtrl) {
|
|
/* WS_EX_CRLASMAINWIN is also need to check.*/
|
|
//if (pCtrl->dwStyle & WS_VISIBLE &&
|
|
// !(pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN))
|
|
if (pCtrl->dwStyle & WS_VISIBLE) {
|
|
maskrect = pCtrl->mask_rects;
|
|
if (!maskrect) {
|
|
rect.left = pCtrl->left;
|
|
rect.top = pCtrl->top;
|
|
rect.right = pCtrl->right;
|
|
rect.bottom = pCtrl->bottom;
|
|
if (PtInRect (&rect, x, y)) {
|
|
hitcode = SendAsyncMessage((HWND)pCtrl, MSG_HITTEST,
|
|
(WPARAM)x, (LPARAM)y);
|
|
if (hitcode != HT_OUT && hitcode != HT_TRANSPARENT) {
|
|
if (UndHitCode) {
|
|
*UndHitCode = hitcode;
|
|
}
|
|
return pCtrl;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
idx = 0;
|
|
do {
|
|
rect.left = (maskrect + idx)->left + pCtrl->left;
|
|
rect.top = (maskrect + idx)->top + pCtrl->top;
|
|
rect.right = (maskrect + idx)->right + pCtrl->left;
|
|
rect.bottom = (maskrect + idx)->bottom + pCtrl->top;
|
|
if (PtInRect (&rect, x, y)) {
|
|
hitcode = SendAsyncMessage((HWND)pCtrl, MSG_HITTEST,
|
|
(WPARAM)x, (LPARAM)y);
|
|
if (hitcode != HT_OUT && hitcode != HT_TRANSPARENT) {
|
|
if (UndHitCode) {
|
|
*UndHitCode = hitcode;
|
|
}
|
|
return pCtrl;
|
|
}
|
|
|
|
/** ignore this control and check the next */
|
|
break;
|
|
}
|
|
|
|
idx = (maskrect + idx)->next;
|
|
} while (idx != 0);
|
|
}
|
|
}
|
|
pCtrl = pCtrl->prev;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
HWND GUIAPI GetWindowUnderCursor (void)
|
|
{
|
|
POINT pt;
|
|
PCONTROL pCtrl, pchild;
|
|
int cx, cy;
|
|
|
|
GetCursorPos (&pt);
|
|
|
|
pCtrl = (PCONTROL)gui_GetMainWindowPtrUnderPoint (pt.x, pt.y);
|
|
if (!pCtrl) return 0;
|
|
|
|
do {
|
|
cx = pt.x; cy = pt.y;
|
|
ScreenToClient ((HWND)pCtrl, &cx, &cy);
|
|
pchild = wndMouseInWhichControl ((PMAINWIN)pCtrl, cx, cy, NULL);
|
|
if (!pchild) break;
|
|
pCtrl = pchild;
|
|
} while (1);
|
|
|
|
return (HWND)pCtrl;
|
|
}
|
|
|
|
HWND GUIAPI WindowFromPointEx (POINT pt, BOOL bRecursion)
|
|
{
|
|
HWND hChild;
|
|
HWND hParent = (HWND)gui_GetMainWindowPtrUnderPoint (pt.x, pt.y);
|
|
|
|
if (hParent && bRecursion) {
|
|
ScreenToClient(hParent, &pt.x, &pt.y);
|
|
hChild = ChildWindowFromPointEx(hParent, pt,
|
|
CWP_SKIPINVISIBLE | CWP_SKIPDISABLED);
|
|
|
|
while (hChild != HWND_NULL) {
|
|
ClientToScreen(hParent, &pt.x, &pt.y);
|
|
ScreenToClient(hChild, &pt.x, &pt.y);
|
|
|
|
hParent = hChild;
|
|
hChild = ChildWindowFromPointEx(hParent, pt,
|
|
CWP_SKIPINVISIBLE | CWP_SKIPDISABLED);
|
|
//TODO:not support static control
|
|
}
|
|
|
|
return IsWindow(hChild)?hChild:hParent;
|
|
}
|
|
else
|
|
return hParent;
|
|
|
|
return HWND_NULL;
|
|
}
|
|
|
|
//should found the above(last created) control, not previous created window.
|
|
HWND GUIAPI ChildWindowFromPointEx (HWND hParent, POINT pt, UINT uFlags)
|
|
{
|
|
PMAINWIN pWin;
|
|
PCONTROL pCtrl;
|
|
HWND pRet = HWND_NULL;
|
|
RECT rect;
|
|
unsigned short idx;
|
|
MASKRECT *maskrect;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hParent), HWND_NULL);
|
|
pWin = MG_GET_WINDOW_PTR (hParent);
|
|
|
|
pCtrl = (PCONTROL)(pWin->hFirstChild);
|
|
while (pCtrl) {
|
|
if ((uFlags & CWP_SKIPINVISIBLE) && !(pCtrl->dwStyle & WS_VISIBLE)) {
|
|
pCtrl = pCtrl->next;
|
|
continue;
|
|
}
|
|
if ((uFlags & CWP_SKIPDISABLED) && (pCtrl->dwStyle & WS_DISABLED)) {
|
|
pCtrl = pCtrl->next;
|
|
continue;
|
|
}
|
|
if ((uFlags & CWP_SKIPTRANSPARENT) && (pCtrl->dwExStyle & WS_EX_TRANSPARENT)) {
|
|
pCtrl = pCtrl->next;
|
|
continue;
|
|
}
|
|
|
|
maskrect = pCtrl->mask_rects;
|
|
if (!maskrect) {
|
|
rect.left = pCtrl->left;
|
|
rect.top = pCtrl->top;
|
|
rect.right = pCtrl->right;
|
|
rect.bottom = pCtrl->bottom;
|
|
if (PtInRect (&rect, pt.x, pt.y)) {
|
|
pRet = (HWND)pCtrl;
|
|
pCtrl = pCtrl->next;
|
|
continue;
|
|
}
|
|
}
|
|
else {
|
|
idx = 0;
|
|
do {
|
|
rect.left = (maskrect + idx)->left + pCtrl->left;
|
|
rect.top = (maskrect + idx)->top + pCtrl->top;
|
|
rect.right = (maskrect + idx)->right + pCtrl->left;
|
|
rect.bottom = (maskrect + idx)->bottom + pCtrl->top;
|
|
if (PtInRect (&rect, pt.x, pt.y)) {
|
|
pRet = (HWND)pCtrl;
|
|
break;
|
|
}
|
|
|
|
idx = (maskrect + idx)->next;
|
|
} while (idx != 0);
|
|
}
|
|
|
|
pCtrl = pCtrl->next;
|
|
}
|
|
|
|
return pRet;
|
|
}
|
|
|
|
/* NOTE:
|
|
** this function is CONTROL mouse messages handler,
|
|
** can automaticly capture mouse depend on HITTEST code.
|
|
*/
|
|
|
|
static PCONTROL __mgs_captured_ctrl = NULL;
|
|
|
|
void __mg_reset_mainwin_capture_info (PCONTROL ctrl)
|
|
{
|
|
if ((ctrl == NULL || ctrl == __mgs_captured_ctrl)
|
|
|| (__mgs_captured_ctrl
|
|
&& __mgs_captured_ctrl->pMainWin == (PMAINWIN)ctrl)) {
|
|
POINT mousePos;
|
|
|
|
ReleaseCapture ();
|
|
__mgs_captured_ctrl = NULL;
|
|
|
|
GetCursorPos (&mousePos);
|
|
PostMessage (HWND_DESKTOP, MSG_MOUSEMOVE,
|
|
0, MAKELONG (mousePos.x, mousePos.y));
|
|
}
|
|
}
|
|
|
|
static LRESULT DefaultDTMouseMsgHandler (PMAINWIN pWin, UINT message,
|
|
WPARAM flags, int x, int y)
|
|
{
|
|
int hc_mainwin = HT_UNKNOWN;
|
|
int cx, cy;
|
|
PCONTROL pCtrl = NULL;
|
|
|
|
if (pWin->dwStyle & WS_DISABLED)
|
|
return 0;
|
|
|
|
cx = x - pWin->cl;
|
|
cy = y - pWin->ct;
|
|
|
|
/* houhh 20081023, BUGFIX for can not click combox's listbox
|
|
* out of Mainwin.*/
|
|
pCtrl = wndMouseInWhichControl (pWin, cx, cy, &hc_mainwin);
|
|
if (pCtrl == NULL) {
|
|
hc_mainwin = SendAsyncMessage((HWND)pWin, MSG_HITTEST,
|
|
(WPARAM)x, (LPARAM)y);
|
|
pCtrl = (PCONTROL)pWin;
|
|
}
|
|
else {
|
|
hc_mainwin = HT_CLIENT;
|
|
}
|
|
|
|
/* houhh 20080804, if click on scrollbar of mainwin's control, then
|
|
* need to change hc_mainwin, else click on scrollbar of mainwin,
|
|
* hc_mainwin can not change to HT_CLIENT. */
|
|
|
|
if (pCtrl && pCtrl->WinType == TYPE_CONTROL &&
|
|
(hc_mainwin >= HT_SB_LEFTARROW &&
|
|
hc_mainwin <= HT_SB_VTHUMB))
|
|
hc_mainwin = HT_CLIENT;
|
|
|
|
switch (message) {
|
|
case MSG_DT_MOUSEMOVE:
|
|
if (hc_mainwin == HT_CLIENT) {
|
|
PostMessage ((HWND)pWin, MSG_SETCURSOR,
|
|
0, MAKELONG (cx, cy));
|
|
}
|
|
else {
|
|
PostMessage ((HWND)pWin, MSG_NCSETCURSOR,
|
|
hc_mainwin, MAKELONG (cx, cy));
|
|
}
|
|
// fallthrough
|
|
case MSG_DT_LBUTTONDBLCLK:
|
|
case MSG_DT_RBUTTONDBLCLK:
|
|
if (hc_mainwin == HT_CLIENT) {
|
|
PostMessage((HWND)pWin,
|
|
message + (MSG_NCMOUSEOFF - MSG_DT_MOUSEOFF),
|
|
hc_mainwin, MAKELONG (x, y));
|
|
PostMessage((HWND)pWin,
|
|
message - MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG (cx, cy));
|
|
}
|
|
else {
|
|
PostMessage((HWND)pWin,
|
|
message + (MSG_NCMOUSEOFF - MSG_DT_MOUSEOFF),
|
|
hc_mainwin, MAKELONG (x, y));
|
|
}
|
|
break;
|
|
|
|
case MSG_DT_LBUTTONDOWN:
|
|
case MSG_DT_RBUTTONDOWN:
|
|
if (hc_mainwin != HT_CLIENT) {
|
|
PostMessage ((HWND)pWin,
|
|
message + (MSG_NCMOUSEOFF - MSG_DT_MOUSEOFF),
|
|
hc_mainwin, MAKELONG (x, y));
|
|
}
|
|
else {
|
|
PostMessage((HWND)pWin,
|
|
message - MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG(cx, cy));
|
|
}
|
|
break;
|
|
|
|
case MSG_DT_LBUTTONUP:
|
|
case MSG_DT_RBUTTONUP:
|
|
if (hc_mainwin == HT_CLIENT) {
|
|
PostMessage((HWND)pWin,
|
|
message - MSG_DT_MOUSEOFF,
|
|
flags, MAKELONG(cx, cy));
|
|
}
|
|
else {
|
|
PostMessage ((HWND)pWin,
|
|
message + (MSG_NCMOUSEOFF - MSG_DT_MOUSEOFF),
|
|
hc_mainwin, MAKELONG (x, y));
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT DefaultMouseMsgHandler (PMAINWIN pWin, UINT message,
|
|
WPARAM flags, int x, int y)
|
|
{
|
|
static PMAINWIN __mgs_captured_win = NULL;
|
|
PCONTROL pUnderPointer;
|
|
int CapHitCode = HT_UNKNOWN;
|
|
int UndHitCode = HT_UNKNOWN;
|
|
int cx = 0, cy = 0;
|
|
|
|
if (__mgs_captured_ctrl) {
|
|
/* convert to parent window's client coordinates. */
|
|
ScreenToClient ((HWND)__mgs_captured_win, &x, &y);
|
|
|
|
CapHitCode = SendAsyncMessage((HWND)__mgs_captured_ctrl, MSG_HITTEST,
|
|
(WPARAM)x, (LPARAM)y);
|
|
|
|
pUnderPointer = NULL;
|
|
}
|
|
else {
|
|
pUnderPointer = wndMouseInWhichControl (pWin, x, y, &UndHitCode);
|
|
if (pUnderPointer && (pUnderPointer->dwStyle & WS_DISABLED))
|
|
pUnderPointer = NULL;
|
|
|
|
|
|
if (pUnderPointer) {
|
|
cx = x - pUnderPointer->cl;
|
|
cy = y - pUnderPointer->ct;
|
|
}
|
|
}
|
|
|
|
switch (message) {
|
|
case MSG_MOUSEMOVE:
|
|
if (__mgs_captured_ctrl)
|
|
PostMessage((HWND)__mgs_captured_ctrl, MSG_NCMOUSEMOVE,
|
|
CapHitCode, MAKELONG (x, y));
|
|
else {
|
|
if (pWin->hOldUnderPointer != (HWND)pUnderPointer) {
|
|
if (pWin->hOldUnderPointer) {
|
|
PostMessage ((HWND)pWin->hOldUnderPointer,
|
|
MSG_MOUSEMOVEIN, FALSE, (LPARAM)pUnderPointer);
|
|
PostMessage ((HWND)pWin->hOldUnderPointer,
|
|
MSG_NCMOUSEMOVE, HT_OUT, MAKELONG (x, y));
|
|
}
|
|
|
|
if (pUnderPointer)
|
|
PostMessage ((HWND)pUnderPointer, MSG_MOUSEMOVEIN,
|
|
TRUE, (LPARAM)pWin->hOldUnderPointer);
|
|
|
|
pWin->hOldUnderPointer = (HWND)pUnderPointer;
|
|
}
|
|
|
|
if (pUnderPointer == NULL) {
|
|
pWin->hOldUnderPointer = 0;
|
|
break;
|
|
}
|
|
|
|
if (pUnderPointer->dwStyle & WS_DISABLED) {
|
|
SetCursor (GetSystemCursor (IDC_ARROW));
|
|
break;
|
|
}
|
|
|
|
if (UndHitCode == HT_CLIENT) {
|
|
PostMessage ((HWND)pUnderPointer,
|
|
MSG_SETCURSOR, 0, MAKELONG (cx, cy));
|
|
|
|
PostMessage((HWND)pUnderPointer, MSG_NCMOUSEMOVE,
|
|
UndHitCode, MAKELONG (x, y));
|
|
PostMessage((HWND)pUnderPointer, MSG_MOUSEMOVE,
|
|
flags, MAKELONG (cx, cy));
|
|
}
|
|
else
|
|
{
|
|
PostMessage((HWND)pUnderPointer, MSG_NCSETCURSOR,
|
|
UndHitCode, MAKELONG (x, y));
|
|
PostMessage((HWND)pUnderPointer, MSG_NCMOUSEMOVE,
|
|
UndHitCode, MAKELONG (x, y));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MSG_LBUTTONDOWN:
|
|
case MSG_RBUTTONDOWN:
|
|
case MSG_MBUTTONDOWN:
|
|
if (pUnderPointer) {
|
|
if (pUnderPointer->dwStyle & WS_DISABLED) {
|
|
Ping ();
|
|
break;
|
|
}
|
|
|
|
SendNotifyMessage ((HWND) pUnderPointer,
|
|
MSG_MOUSEACTIVE, UndHitCode, 0);
|
|
|
|
if (UndHitCode != HT_CLIENT) {
|
|
if (UndHitCode & HT_NEEDCAPTURE
|
|
&& message == MSG_LBUTTONDOWN) {
|
|
SetCapture ((HWND)pWin);
|
|
__mgs_captured_win = pWin;
|
|
__mgs_captured_ctrl = pUnderPointer;
|
|
}
|
|
else
|
|
__mgs_captured_ctrl = NULL;
|
|
|
|
PostMessage ((HWND)pUnderPointer, message + MSG_NCMOUSEOFF,
|
|
UndHitCode, MAKELONG (x, y));
|
|
}
|
|
else if (__mgs_captured_ctrl == NULL) {
|
|
PostMessage((HWND)pUnderPointer, message,
|
|
flags, MAKELONG(cx, cy));
|
|
}
|
|
}
|
|
else if (pWin->hActiveChild) {
|
|
SendNotifyMessage (pWin->hActiveChild,
|
|
MSG_MOUSEACTIVE, HT_OUT, 0);
|
|
PostMessage (pWin->hActiveChild, message + MSG_NCMOUSEOFF,
|
|
HT_OUT, MAKELONG(x, y));
|
|
}
|
|
break;
|
|
|
|
case MSG_RBUTTONUP:
|
|
case MSG_LBUTTONUP:
|
|
case MSG_MBUTTONUP:
|
|
if (__mgs_captured_ctrl && message == MSG_LBUTTONUP) {
|
|
PostMessage ((HWND)__mgs_captured_ctrl,
|
|
message + MSG_NCMOUSEOFF,
|
|
CapHitCode, MAKELONG (x, y));
|
|
ReleaseCapture ();
|
|
__mgs_captured_win = NULL;
|
|
__mgs_captured_ctrl = NULL;
|
|
}
|
|
else if (pUnderPointer) {
|
|
if (pUnderPointer->dwStyle & WS_DISABLED) {
|
|
break;
|
|
}
|
|
|
|
if (UndHitCode == HT_CLIENT)
|
|
PostMessage((HWND)pUnderPointer, message,
|
|
flags, MAKELONG (cx, cy));
|
|
else
|
|
PostMessage((HWND)pUnderPointer, message + MSG_NCMOUSEOFF,
|
|
UndHitCode, MAKELONG (x, y));
|
|
}
|
|
else if (pWin->hActiveChild) {
|
|
PostMessage(pWin->hActiveChild, message + MSG_NCMOUSEOFF,
|
|
HT_OUT, MAKELONG(x, y));
|
|
}
|
|
break;
|
|
|
|
case MSG_LBUTTONDBLCLK:
|
|
case MSG_RBUTTONDBLCLK:
|
|
case MSG_MBUTTONDBLCLK:
|
|
if (pUnderPointer) {
|
|
if (pUnderPointer->dwStyle & WS_DISABLED) {
|
|
Ping ();
|
|
break;
|
|
}
|
|
|
|
if (UndHitCode == HT_CLIENT)
|
|
PostMessage((HWND)pUnderPointer, message,
|
|
flags, MAKELONG(cx, cy));
|
|
else
|
|
PostMessage((HWND)pUnderPointer, message + MSG_NCMOUSEOFF,
|
|
UndHitCode, MAKELONG (x, y));
|
|
}
|
|
else {
|
|
if (pWin->hActiveChild) {
|
|
PostMessage(pWin->hActiveChild, message + MSG_NCMOUSEOFF,
|
|
HT_OUT, MAKELONG(x, y));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL wndGetVScrollBarRect (const MAINWIN* pWin,
|
|
RECT* rcVBar)
|
|
{
|
|
if (pWin->dwStyle & WS_VSCROLL) {
|
|
if (!GetWindowInfo((HWND)pWin)->we_rdr->calc_we_area (
|
|
(HWND)pWin, HT_VSCROLL, rcVBar))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL wndGetHScrollBarRect (const MAINWIN* pWin,
|
|
RECT* rcHBar)
|
|
{
|
|
if (pWin->dwStyle & WS_HSCROLL) {
|
|
if (!GetWindowInfo((HWND)pWin)->we_rdr->calc_we_area (
|
|
(HWND)pWin, HT_HSCROLL, rcHBar))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/* rc: position relative to secondary_dc, so need transform
|
|
* it relative to real_dc(screen).*/
|
|
void __mg_update_secondary_dc (PMAINWIN pWin, HDC secondary_dc,
|
|
HDC real_dc, const RECT* update_rc, DWORD flags)
|
|
{
|
|
RECT wnd_rc, clip_rc, client_rc;
|
|
|
|
if (!dc_IsVisible((PDC)secondary_dc))
|
|
return;
|
|
if (!pWin->pMainWin->secondaryDC) {
|
|
return;
|
|
}
|
|
|
|
/* calculate offset postion. */
|
|
if (flags == HT_CLIENT) {
|
|
gui_WndClientRect ((HWND)pWin, &wnd_rc);
|
|
}
|
|
else {
|
|
gui_WndRect ((HWND)pWin, &wnd_rc);
|
|
}
|
|
|
|
/* 1. clip_rc.left/clip_rc.top is real_rc update in the screen (coordinate
|
|
* relative to screen).
|
|
* 2. clip_rc.left/clip_rc.top need translate update_rc to relative
|
|
* position of the the main window.
|
|
*
|
|
* XXX (VW): Use pWin->pMainWin->left and pWin->pMainWin->top to calculate
|
|
* the offset instead of real_dc's DevRC.
|
|
*/
|
|
clip_rc.left = wnd_rc.left + update_rc->left - pWin->pMainWin->left;
|
|
clip_rc.top = wnd_rc.top + update_rc->top - pWin->pMainWin->top;
|
|
clip_rc.right = clip_rc.left + RECTWP(update_rc);
|
|
clip_rc.bottom = clip_rc.top + RECTHP(update_rc);
|
|
|
|
IncludeClipRect (real_dc, &clip_rc);
|
|
|
|
/* exclude client rect. get non-client region.*/
|
|
if (flags == HT_BORDER) {
|
|
CopyRect (&client_rc, (const RECT*)&pWin->cl);
|
|
/* houhh 20090804, should be convert client_rc to relative pMainWin.*/
|
|
if (IsControl((HWND)pWin)) {
|
|
ClientToWindow((HWND)pWin->pMainWin, &client_rc.left, &client_rc.top);
|
|
ClientToWindow((HWND)pWin->pMainWin, &client_rc.right, &client_rc.bottom);
|
|
}
|
|
else
|
|
OffsetRect (&client_rc, -pWin->pMainWin->left, -pWin->pMainWin->top);
|
|
ExcludeClipRect (real_dc, &client_rc);
|
|
}
|
|
|
|
/* exclude tranparent client rect.*/
|
|
if (flags == HT_CLIENT) {
|
|
PCONTROL child;
|
|
RECT update_rc = pWin->pMainWin->update_rc;
|
|
child = (PCONTROL)pWin->hFirstChild;
|
|
while (child) {
|
|
//if ((child->dwStyle & WS_VISIBLE) && (child->dwExStyle & WS_EX_TRANSPARENT)
|
|
if ((child->dwStyle & WS_VISIBLE)
|
|
&& DoesIntersect ((const RECT*)&child->left, &update_rc)) {
|
|
RECT rcTmp;
|
|
gui_WndClientRect ((HWND)child, &rcTmp);
|
|
ScreenToClient ((HWND)pWin->pMainWin,
|
|
&rcTmp.left, &rcTmp.top);
|
|
ScreenToClient ((HWND)pWin->pMainWin,
|
|
&rcTmp.right, &rcTmp.bottom);
|
|
ExcludeClipRect (real_dc, &rcTmp);
|
|
}
|
|
child = child->next;
|
|
}
|
|
}
|
|
|
|
if (pWin->pMainWin->update_secdc == ON_UPDSECDC_DEFAULT) {
|
|
BitBlt (secondary_dc, update_rc->left, update_rc->top,
|
|
RECTWP(update_rc), RECTHP(update_rc),
|
|
real_dc, clip_rc.left, clip_rc.top, 0);
|
|
}
|
|
else if (pWin->pMainWin->update_secdc != ON_UPDSECDC_DONOTHING) {
|
|
if (flags == HT_CLIENT){
|
|
RECT main_update_rc;
|
|
SetRect(&main_update_rc, clip_rc.left, clip_rc.top,
|
|
clip_rc.right, clip_rc.bottom);
|
|
ClientToWindow((HWND)pWin->pMainWin,
|
|
&main_update_rc.left, &main_update_rc.top);
|
|
ClientToWindow((HWND)pWin->pMainWin,
|
|
&main_update_rc.right, &main_update_rc.bottom);
|
|
pWin->pMainWin->update_secdc ((HWND)pWin,
|
|
secondary_dc, real_dc, update_rc, &clip_rc, &main_update_rc);
|
|
}
|
|
else {
|
|
pWin->pMainWin->update_secdc ((HWND)pWin,
|
|
secondary_dc, real_dc, update_rc, &clip_rc, &clip_rc);
|
|
}
|
|
}
|
|
|
|
//SyncUpdateDC (real_dc);
|
|
}
|
|
|
|
static void draw_secondary_nc_area (PMAINWIN pWin,
|
|
const WINDOW_ELEMENT_RENDERER* rdr,
|
|
HDC hdc, DWORD flags)
|
|
{
|
|
RECT rc;
|
|
HDC real_dc = 0;
|
|
|
|
do {
|
|
#if 0
|
|
/* houhh 20081012, the WS_EX_CTRLASMAINWIN style window have itself's pdc->pGCRInfo
|
|
* information, so the real_dc's global clip info should use itselft's. */
|
|
if (pWin->dwExStyle & WS_EX_CTRLASMAINWIN)
|
|
real_dc = GetDC ((HWND)pWin);
|
|
else
|
|
real_dc = GetDC ((HWND)pWin->pMainWin);
|
|
#else
|
|
real_dc = GetDC ((HWND)pWin->pMainWin);
|
|
#endif
|
|
|
|
if (rdr->calc_we_area ((HWND)pWin, flags, &rc))
|
|
break;
|
|
|
|
if (!IsRectEmpty(&rc)){
|
|
__mg_update_secondary_dc (pWin, hdc, real_dc, &rc, flags);
|
|
}
|
|
} while (FALSE);
|
|
|
|
if (real_dc)
|
|
ReleaseDC (real_dc);
|
|
}
|
|
|
|
static void ShrinkScrollbarClipRect(HWND hWnd, HDC hdc, const WINDOWINFO *_info, int downCode)
|
|
{
|
|
static HWND hWnd_old;
|
|
static LFSCROLLBARINFO vscroll_old;
|
|
static LFSCROLLBARINFO hscroll_old;
|
|
WINDOWINFO *info = (WINDOWINFO *)_info;
|
|
RECT rc_bound, rc_new, rc_old;
|
|
LFSCROLLBARINFO *p_scrollbar_info_old, *p_scrollbar_info_new;
|
|
LFSCROLLBARINFO scrollbar_info_bak;
|
|
int which;
|
|
|
|
if (hWnd != hWnd_old) {
|
|
hWnd_old = hWnd;
|
|
memset(&vscroll_old, 0, sizeof(vscroll_old));
|
|
memset(&hscroll_old, 0, sizeof(hscroll_old));
|
|
return;
|
|
}
|
|
|
|
if (downCode == HT_VSCROLL) {
|
|
p_scrollbar_info_old = &vscroll_old;
|
|
p_scrollbar_info_new = &info->vscroll;
|
|
which = HT_SB_VTHUMB;
|
|
}else if (downCode == HT_HSCROLL) {
|
|
p_scrollbar_info_old = &hscroll_old;
|
|
p_scrollbar_info_new = &info->hscroll;
|
|
which = HT_SB_HTHUMB;
|
|
}else{
|
|
return;
|
|
}
|
|
|
|
if (1
|
|
&& p_scrollbar_info_old->minPos == p_scrollbar_info_new->minPos
|
|
&& p_scrollbar_info_old->maxPos == p_scrollbar_info_new->maxPos
|
|
&& p_scrollbar_info_old->curPos != p_scrollbar_info_new->curPos /* Yes, != */
|
|
&& p_scrollbar_info_old->pageStep == p_scrollbar_info_new->pageStep
|
|
&& p_scrollbar_info_old->arrowLen == p_scrollbar_info_new->arrowLen
|
|
/* barStart */
|
|
&& p_scrollbar_info_old->barLen == p_scrollbar_info_new->barLen
|
|
&& p_scrollbar_info_old->status == p_scrollbar_info_new->status) {
|
|
info->we_rdr->calc_we_area(hWnd, which, &rc_new);
|
|
|
|
memcpy(&scrollbar_info_bak, p_scrollbar_info_new, sizeof(scrollbar_info_bak));
|
|
memcpy(p_scrollbar_info_new, p_scrollbar_info_old, sizeof(scrollbar_info_bak));
|
|
info->we_rdr->calc_we_area(hWnd, which, &rc_old);
|
|
memcpy(p_scrollbar_info_new, &scrollbar_info_bak, sizeof(scrollbar_info_bak));
|
|
|
|
GetBoundRect(&rc_bound, &rc_new, &rc_old);
|
|
|
|
/* [humingming.2010.9.7] for problem fashion render draw scrollbar's thumb framework bound.
|
|
* why add 1 pixel? don't answer me, try this code with MiniGUI:
|
|
*
|
|
* SetRect (&rc_bound, 10, 10, 10+50, 10+50);
|
|
* SetPenColor (hdc, PIXEL_blue);
|
|
* SetBrushColor (hdc, PIXEL_red);
|
|
*
|
|
* MoveTo (hdc, rc_bound.left, rc_bound.top);
|
|
* LineTo (hdc, rc_bound.right, rc_bound.top);
|
|
* LineTo (hdc, rc_bound.right, rc_bound.bottom);
|
|
* LineTo (hdc, rc_bound.left, rc_bound.bottom);
|
|
* LineTo (hdc, rc_bound.left, rc_bound.top);
|
|
*
|
|
* ClipRectIntersect(hdc, &rc_bound);
|
|
* FillBox (hdc, 0, 0, 500, 400);
|
|
*
|
|
* you check bound of the box's right and bottom carefully, and you will konw it. -_-||
|
|
*/
|
|
rc_bound.right += 1;
|
|
rc_bound.bottom += 1;
|
|
|
|
#if 0 /* to show the clip rect */
|
|
SetBrushColor(hdc, RGB2Pixel(hdc, 0xff, 0, 0));
|
|
FillBox(hdc, rc_bound.left, rc_bound.top, RECTW(rc_bound), RECTH(rc_bound));
|
|
usleep(100);
|
|
#endif
|
|
ClipRectIntersect(hdc, &rc_bound);
|
|
}
|
|
|
|
memcpy(p_scrollbar_info_old, p_scrollbar_info_new, sizeof(scrollbar_info_bak));
|
|
}
|
|
|
|
#define wndDrawNCButton(pWin, downCode, status) wndDrawNCButtonEx(pWin, 0, downCode, status)
|
|
|
|
static BOOL wndDrawNCButtonEx (PMAINWIN pWin, HDC hdc, int downCode, int status)
|
|
{
|
|
BOOL fGetDC = FALSE;
|
|
const WINDOWINFO *info = GetWindowInfo ((HWND)pWin);
|
|
static int _status =
|
|
SBS_PRESSED_LTUP | SBS_PRESSED_BTDN | SBS_PRESSED_THUMB |
|
|
SBS_HILITE_LTUP | SBS_HILITE_BTDN | SBS_HILITE_THUMB;
|
|
|
|
if(hdc == 0)
|
|
{
|
|
hdc = get_valid_dc (pWin, FALSE);
|
|
fGetDC = TRUE;
|
|
}
|
|
|
|
switch (downCode) {
|
|
case HT_ICON:
|
|
case HT_MAXBUTTON:
|
|
case HT_MINBUTTON:
|
|
case HT_CLOSEBUTTON: {
|
|
BOOL is_active = TRUE;
|
|
if (pWin->WinType == TYPE_MAINWIN)
|
|
is_active = !(pWin->dwStyle & WS_DISABLED) &&
|
|
(GetActiveWindow() == (HWND)pWin);
|
|
else
|
|
is_active = !(pWin->dwStyle & WS_DISABLED) &&
|
|
(((PCONTROL)pWin)->pParent->active == (PCONTROL)pWin);
|
|
|
|
if (is_active)
|
|
info->we_rdr->draw_caption_button ((HWND)pWin,
|
|
hdc, downCode, LFRDR_BTN_STATUS_NORMAL|status);
|
|
else
|
|
info->we_rdr->draw_caption_button ((HWND)pWin,
|
|
hdc, downCode, LFRDR_BTN_STATUS_INACTIVE|status);
|
|
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, info->we_rdr, hdc, downCode);
|
|
}
|
|
release_valid_dc (pWin, hdc);
|
|
return TRUE;
|
|
}
|
|
|
|
case HT_SB_UPARROW: {
|
|
if (pWin->vscroll.curPos == pWin->vscroll.minPos) {
|
|
pWin->vscroll.status |= SBS_DISABLED_LTUP;
|
|
}
|
|
else {
|
|
pWin->vscroll.status &= ~SBS_DISABLED_LTUP;
|
|
}
|
|
|
|
if (status == LFRDR_BTN_STATUS_PRESSED)
|
|
pWin->vscroll.status |= SBS_PRESSED_LTUP;
|
|
else if (status == LFRDR_BTN_STATUS_HILITE)
|
|
pWin->vscroll.status |= SBS_HILITE_LTUP;
|
|
|
|
if (pWin->vscroll.curPos + pWin->vscroll.pageStep - 1
|
|
>= pWin->vscroll.maxPos)
|
|
pWin->vscroll.status |= SBS_DISABLED_BTDN;
|
|
else
|
|
pWin->vscroll.status &= ~SBS_DISABLED_BTDN;
|
|
|
|
break;
|
|
}
|
|
|
|
case HT_SB_DOWNARROW: {
|
|
if (pWin->vscroll.curPos + pWin->vscroll.pageStep - 1
|
|
>= pWin->vscroll.maxPos) {
|
|
pWin->vscroll.status |= SBS_DISABLED_BTDN;
|
|
}
|
|
else {
|
|
pWin->vscroll.status &= ~SBS_DISABLED_BTDN;
|
|
}
|
|
|
|
if (status == LFRDR_BTN_STATUS_PRESSED)
|
|
pWin->vscroll.status |= SBS_PRESSED_BTDN;
|
|
else if (status == LFRDR_BTN_STATUS_HILITE)
|
|
pWin->vscroll.status |= SBS_HILITE_BTDN;
|
|
|
|
if (pWin->vscroll.curPos == pWin->vscroll.minPos)
|
|
pWin->vscroll.status |= SBS_DISABLED_LTUP;
|
|
else
|
|
pWin->vscroll.status &= ~SBS_DISABLED_LTUP;
|
|
|
|
break;
|
|
}
|
|
|
|
case HT_SB_LEFTARROW: {
|
|
if (pWin->hscroll.curPos == pWin->hscroll.minPos) {
|
|
pWin->hscroll.status |= SBS_DISABLED_LTUP;
|
|
}
|
|
else {
|
|
pWin->hscroll.status &= ~SBS_DISABLED_LTUP;
|
|
}
|
|
|
|
if (status == LFRDR_BTN_STATUS_PRESSED)
|
|
pWin->hscroll.status |= SBS_PRESSED_LTUP;
|
|
else if (status == LFRDR_BTN_STATUS_HILITE)
|
|
pWin->hscroll.status |= SBS_HILITE_LTUP;
|
|
|
|
if (pWin->hscroll.curPos + pWin->hscroll.pageStep - 1
|
|
>= pWin->hscroll.maxPos)
|
|
pWin->hscroll.status |= SBS_DISABLED_BTDN;
|
|
else
|
|
pWin->hscroll.status &= ~SBS_DISABLED_BTDN;
|
|
|
|
break;
|
|
}
|
|
|
|
case HT_SB_RIGHTARROW: {
|
|
if (pWin->hscroll.curPos + pWin->hscroll.pageStep - 1
|
|
>= pWin->hscroll.maxPos) {
|
|
pWin->hscroll.status |= SBS_DISABLED_BTDN;
|
|
}
|
|
else {
|
|
pWin->hscroll.status &= ~SBS_DISABLED_BTDN;
|
|
}
|
|
|
|
if (status == LFRDR_BTN_STATUS_PRESSED)
|
|
pWin->hscroll.status |= SBS_PRESSED_BTDN;
|
|
else if (status == LFRDR_BTN_STATUS_HILITE)
|
|
pWin->hscroll.status |= SBS_HILITE_BTDN;
|
|
|
|
if (pWin->hscroll.curPos == pWin->hscroll.minPos)
|
|
pWin->hscroll.status |= SBS_DISABLED_LTUP;
|
|
else
|
|
pWin->hscroll.status &= ~SBS_DISABLED_LTUP;
|
|
|
|
break;
|
|
}
|
|
|
|
case HT_SB_HTHUMB: {
|
|
if (status == LFRDR_BTN_STATUS_HILITE)
|
|
pWin->hscroll.status |= SBS_HILITE_THUMB;
|
|
|
|
if (pWin->hscroll.curPos == pWin->hscroll.minPos)
|
|
pWin->hscroll.status |= SBS_DISABLED_LTUP;
|
|
else
|
|
pWin->hscroll.status &= ~SBS_DISABLED_LTUP;
|
|
|
|
if (pWin->hscroll.curPos + pWin->hscroll.pageStep - 1
|
|
>= pWin->hscroll.maxPos)
|
|
pWin->hscroll.status |= SBS_DISABLED_BTDN;
|
|
else
|
|
pWin->hscroll.status &= ~SBS_DISABLED_BTDN;
|
|
|
|
if (pWin->hscroll.pageStep < pWin->hscroll.maxPos
|
|
- pWin->hscroll.minPos + 1)
|
|
{
|
|
if (status == LFRDR_BTN_STATUS_PRESSED)
|
|
pWin->hscroll.status |= SBS_PRESSED_THUMB;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case HT_SB_VTHUMB: {
|
|
if (status == LFRDR_BTN_STATUS_HILITE)
|
|
pWin->vscroll.status |= SBS_HILITE_THUMB;
|
|
|
|
if (pWin->vscroll.curPos == pWin->vscroll.minPos)
|
|
pWin->vscroll.status |= SBS_DISABLED_LTUP;
|
|
else
|
|
pWin->vscroll.status &= ~SBS_DISABLED_LTUP;
|
|
|
|
if (pWin->vscroll.curPos + pWin->vscroll.pageStep - 1
|
|
>= pWin->vscroll.maxPos)
|
|
pWin->vscroll.status |= SBS_DISABLED_BTDN;
|
|
else
|
|
pWin->vscroll.status &= ~SBS_DISABLED_BTDN;
|
|
|
|
if (pWin->vscroll.pageStep < pWin->vscroll.maxPos
|
|
- pWin->vscroll.minPos + 1) {
|
|
if (status == LFRDR_BTN_STATUS_PRESSED)
|
|
pWin->vscroll.status |= SBS_PRESSED_THUMB;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case HT_SB_LEFTSPACE:
|
|
case HT_SB_RIGHTSPACE:
|
|
case HT_HSCROLL: {
|
|
if (pWin->hscroll.curPos == pWin->hscroll.minPos)
|
|
pWin->hscroll.status |= SBS_DISABLED_LTUP;
|
|
else
|
|
pWin->hscroll.status &= ~SBS_DISABLED_LTUP;
|
|
|
|
if (pWin->hscroll.curPos + pWin->hscroll.pageStep - 1
|
|
>= pWin->hscroll.maxPos)
|
|
pWin->hscroll.status |= SBS_DISABLED_BTDN;
|
|
else
|
|
pWin->hscroll.status &= ~SBS_DISABLED_BTDN;
|
|
break;
|
|
}
|
|
|
|
case HT_SB_UPSPACE:
|
|
case HT_SB_DOWNSPACE:
|
|
case HT_VSCROLL: {
|
|
if (pWin->vscroll.curPos == pWin->vscroll.minPos)
|
|
pWin->vscroll.status |= SBS_DISABLED_LTUP;
|
|
else
|
|
pWin->vscroll.status &= ~SBS_DISABLED_LTUP;
|
|
|
|
if (pWin->vscroll.curPos + pWin->vscroll.pageStep - 1
|
|
>= pWin->vscroll.maxPos)
|
|
pWin->vscroll.status |= SBS_DISABLED_BTDN;
|
|
else
|
|
pWin->vscroll.status &= ~SBS_DISABLED_BTDN;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
release_valid_dc (pWin, hdc);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!pWin->pMainWin->secondaryDC) {
|
|
ShrinkScrollbarClipRect((HWND)pWin, hdc, info, downCode);
|
|
}
|
|
|
|
info->we_rdr->draw_scrollbar ((HWND)pWin, hdc, downCode);
|
|
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, info->we_rdr, hdc, downCode);
|
|
}
|
|
|
|
if (fGetDC)
|
|
release_valid_dc (pWin, hdc);
|
|
|
|
pWin->hscroll.status &= ~_status;
|
|
pWin->vscroll.status &= ~_status;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
int MenuBarHitTest (HWND hwnd, int x, int y);
|
|
|
|
static void wndTrackMenuBarOnMouseMove(PMAINWIN pWin, int message,
|
|
int location, int x, int y)
|
|
{
|
|
/** do nothing in LFRDR */
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
static int set_hilite_sbpos (int location)
|
|
{
|
|
switch (location) {
|
|
case HT_SB_UPARROW:
|
|
case HT_SB_DOWNARROW:
|
|
case HT_SB_LEFTARROW:
|
|
case HT_SB_RIGHTARROW:
|
|
case HT_SB_HTHUMB:
|
|
case HT_SB_VTHUMB:
|
|
return location;
|
|
default:
|
|
return HT_SB_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
#define CALC_THUMB_HPOS(newBarStart, rcBar, scroll) \
|
|
((rcBar.right - rcBar.left - scroll.barLen) > 0 ? ((newBarStart) * (scroll.maxPos - scroll.minPos - scroll.pageStep + 1) \
|
|
/ (rcBar.right - rcBar.left - scroll.barLen) + scroll.minPos) : 0)
|
|
|
|
static int wndHandleHScrollBar (PMAINWIN pWin,
|
|
int message, int location, int x, int y)
|
|
{
|
|
static int downPos = HT_SB_UNKNOWN;
|
|
static int movePos = HT_SB_UNKNOWN;
|
|
static int hilitePos = HT_SB_UNKNOWN;
|
|
static int sbCode = 0;
|
|
static int oldBarStart;
|
|
static int oldThumbPos;
|
|
static int oldx;
|
|
int newBarStart;
|
|
int newThumbPos = 0;
|
|
RECT rcBar;
|
|
|
|
if (!((location & HT_SB_MASK) == HT_SB_MASK && location < HT_SB_VMASK)
|
|
&& downPos == HT_SB_UNKNOWN && hilitePos == HT_SB_UNKNOWN)
|
|
return 0;
|
|
|
|
if (pWin->hscroll.status & SBS_HIDE ||
|
|
pWin->hscroll.status & SBS_DISABLED)
|
|
return -1;
|
|
|
|
wndGetHScrollBarRect (pWin, &rcBar);
|
|
rcBar.left += GetWindowElementAttr ((HWND)pWin, WE_METRICS_SCROLLBAR);
|
|
rcBar.right -= GetWindowElementAttr ((HWND)pWin, WE_METRICS_SCROLLBAR);
|
|
|
|
switch (message) {
|
|
case MSG_NCLBUTTONDOWN:
|
|
oldBarStart = pWin->hscroll.barStart;
|
|
oldThumbPos = pWin->hscroll.curPos;
|
|
oldx = x;
|
|
|
|
downPos = location;
|
|
movePos = location;
|
|
hilitePos = HT_SB_UNKNOWN;
|
|
|
|
wndDrawNCButton (pWin, location, LFRDR_BTN_STATUS_PRESSED);
|
|
|
|
if (location == HT_SB_LEFTARROW) {
|
|
if (pWin->hscroll.curPos == pWin->hscroll.minPos)
|
|
break;
|
|
|
|
sbCode = SB_LINELEFT;
|
|
}
|
|
else if (location == HT_SB_RIGHTARROW) {
|
|
if (pWin->hscroll.curPos + pWin->hscroll.pageStep
|
|
>= pWin->hscroll.maxPos)
|
|
break;
|
|
|
|
sbCode = SB_LINERIGHT;
|
|
}
|
|
else if (location == HT_SB_LEFTSPACE) {
|
|
if (pWin->hscroll.curPos == pWin->hscroll.minPos)
|
|
break;
|
|
|
|
sbCode = SB_PAGELEFT;
|
|
}
|
|
else if (location == HT_SB_RIGHTSPACE) {
|
|
if (pWin->hscroll.curPos == pWin->hscroll.maxPos)
|
|
break;
|
|
|
|
sbCode = SB_PAGERIGHT;
|
|
}
|
|
else if (location == HT_SB_HTHUMB) {
|
|
sbCode = SB_THUMBTRACK;
|
|
break;
|
|
}
|
|
|
|
if (location != HT_SB_UNKNOWN) {
|
|
SendNotifyMessage ((HWND)pWin, MSG_HSCROLL, sbCode, x);
|
|
SetAutoRepeatMessage ((HWND)pWin, MSG_HSCROLL, sbCode, x);
|
|
}
|
|
break;
|
|
|
|
case MSG_NCLBUTTONUP:
|
|
if (sbCode == SB_THUMBTRACK
|
|
&& downPos == HT_SB_HTHUMB) {
|
|
newBarStart = oldBarStart + x - oldx;
|
|
if (RECTW(rcBar) != 0)
|
|
newThumbPos = CALC_THUMB_HPOS(newBarStart, rcBar, pWin->hscroll);
|
|
|
|
pWin->hscroll.status &= ~SBS_PRESSED_LTUP;
|
|
pWin->hscroll.status &= ~SBS_PRESSED_BTDN;
|
|
|
|
if (newThumbPos < pWin->hscroll.minPos)
|
|
newThumbPos = pWin->hscroll.minPos;
|
|
if (newThumbPos > pWin->hscroll.maxPos)
|
|
newThumbPos = pWin->hscroll.maxPos;
|
|
if (newBarStart != oldBarStart)
|
|
SendNotifyMessage ((HWND)pWin,
|
|
MSG_HSCROLL, SB_THUMBPOSITION, newThumbPos);
|
|
|
|
//wndDrawNCButton (pWin, downPos, LFRDR_BTN_STATUS_NORMAL);
|
|
wndDrawNCButton (pWin, HT_HSCROLL, 0);
|
|
|
|
downPos = HT_SB_UNKNOWN;
|
|
movePos = HT_SB_UNKNOWN;
|
|
hilitePos = HT_SB_UNKNOWN;
|
|
return -1;
|
|
}
|
|
|
|
if (downPos != HT_SB_UNKNOWN) {
|
|
//wndDrawNCButton (pWin, downPos, LFRDR_BTN_STATUS_NORMAL);
|
|
wndDrawNCButton (pWin, HT_HSCROLL, 0);
|
|
SendNotifyMessage ((HWND)pWin, MSG_HSCROLL, SB_ENDSCROLL, 0);
|
|
/* cancel repeat message */
|
|
SetAutoRepeatMessage (0, 0, 0, 0);
|
|
}
|
|
|
|
downPos = HT_SB_UNKNOWN;
|
|
movePos = HT_SB_UNKNOWN;
|
|
hilitePos = HT_SB_UNKNOWN;
|
|
return 0;
|
|
|
|
case MSG_NCMOUSEMOVE:
|
|
if (sbCode == SB_THUMBTRACK
|
|
&& downPos == HT_SB_HTHUMB) {
|
|
newBarStart = oldBarStart + x - oldx;
|
|
if (RECTW(rcBar) != 0)
|
|
newThumbPos = CALC_THUMB_HPOS(newBarStart, rcBar, pWin->hscroll);
|
|
|
|
if (newThumbPos < pWin->hscroll.minPos)
|
|
newThumbPos = pWin->hscroll.minPos;
|
|
if (newThumbPos > pWin->hscroll.maxPos)
|
|
newThumbPos = pWin->hscroll.maxPos;
|
|
if (newThumbPos != oldThumbPos) {
|
|
if (pWin->hscroll.pageStep < pWin->hscroll.maxPos
|
|
- pWin->hscroll.minPos + 1)
|
|
{
|
|
SendNotifyMessage ((HWND)pWin,
|
|
MSG_HSCROLL, SB_THUMBTRACK, newThumbPos);
|
|
oldThumbPos = newThumbPos;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (downPos != HT_SB_UNKNOWN) {
|
|
if (movePos == downPos && location != downPos)
|
|
wndDrawNCButton (pWin, downPos, LFRDR_BTN_STATUS_NORMAL);
|
|
else if (movePos != downPos && location == downPos)
|
|
wndDrawNCButton (pWin, downPos, LFRDR_BTN_STATUS_PRESSED);
|
|
movePos = location;
|
|
}
|
|
else {
|
|
PostMessage((HWND)pWin, MSG_NCSETCURSOR, location, MAKELONG (x, y));
|
|
if (hilitePos != location) {
|
|
if (hilitePos != HT_SB_UNKNOWN)
|
|
wndDrawNCButton (pWin, hilitePos, LFRDR_BTN_STATUS_NORMAL);
|
|
|
|
if (location != HT_SB_UNKNOWN
|
|
&& ((location & HT_SB_MASK) == HT_SB_MASK && location < HT_SB_VMASK))
|
|
wndDrawNCButton (pWin, location, LFRDR_BTN_STATUS_HILITE);
|
|
}
|
|
|
|
if ((location & HT_SB_MASK) == HT_SB_MASK && location < HT_SB_VMASK)
|
|
hilitePos = set_hilite_sbpos (location);
|
|
else
|
|
hilitePos = HT_SB_UNKNOWN;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
#define CALC_THUMB_VPOS(newBarStart, rcBar, scroll) \
|
|
((rcBar.bottom - rcBar.top - scroll.barLen) > 0 ? ((newBarStart) * (scroll.maxPos - scroll.minPos - scroll.pageStep + 1) \
|
|
/ (rcBar.bottom - rcBar.top - scroll.barLen) + scroll.minPos) : 0)
|
|
|
|
static int wndHandleVScrollBar (PMAINWIN pWin,
|
|
int message, int location, int x, int y)
|
|
{
|
|
static int downPos = HT_SB_UNKNOWN;
|
|
static int movePos = HT_SB_UNKNOWN;
|
|
static int hilitePos = HT_SB_UNKNOWN;
|
|
static int sbCode = 0;
|
|
static int oldBarStart;
|
|
static int oldThumbPos;
|
|
static int oldy;
|
|
int newBarStart;
|
|
int newThumbPos = 0;
|
|
RECT rcBar;
|
|
|
|
if ((location & HT_SB_VMASK) != HT_SB_VMASK
|
|
&& downPos == HT_SB_UNKNOWN
|
|
&& hilitePos == HT_SB_UNKNOWN)
|
|
return 0;
|
|
|
|
if (pWin->vscroll.status & SBS_HIDE ||
|
|
pWin->vscroll.status & SBS_DISABLED)
|
|
return -1;
|
|
|
|
wndGetVScrollBarRect (pWin, &rcBar);
|
|
rcBar.top += GetWindowElementAttr ((HWND)pWin, WE_METRICS_SCROLLBAR);
|
|
rcBar.bottom -= GetWindowElementAttr ((HWND)pWin, WE_METRICS_SCROLLBAR);
|
|
|
|
switch (message) {
|
|
case MSG_NCLBUTTONDOWN:
|
|
oldBarStart = pWin->vscroll.barStart;
|
|
oldThumbPos = pWin->vscroll.curPos;
|
|
oldy = y;
|
|
downPos = location;
|
|
movePos = location;
|
|
hilitePos = HT_SB_UNKNOWN;
|
|
|
|
wndDrawNCButton (pWin, location, LFRDR_BTN_STATUS_PRESSED);
|
|
|
|
if (location == HT_SB_UPARROW) {
|
|
if (pWin->vscroll.curPos == pWin->vscroll.minPos)
|
|
break;
|
|
sbCode = SB_LINEUP;
|
|
}
|
|
else if (location == HT_SB_DOWNARROW) {
|
|
if (pWin->vscroll.curPos + pWin->vscroll.pageStep - 1
|
|
>= pWin->vscroll.maxPos)
|
|
break;
|
|
sbCode = SB_LINEDOWN;
|
|
}
|
|
else if (location == HT_SB_UPSPACE) {
|
|
if (pWin->vscroll.curPos == pWin->vscroll.minPos)
|
|
break;
|
|
sbCode = SB_PAGEUP;
|
|
}
|
|
else if (location == HT_SB_DOWNSPACE) {
|
|
if (pWin->vscroll.curPos >= pWin->vscroll.maxPos)
|
|
break;
|
|
sbCode = SB_PAGEDOWN;
|
|
}
|
|
else if (location == HT_SB_VTHUMB) {
|
|
sbCode = SB_THUMBTRACK;
|
|
break;
|
|
}
|
|
|
|
if (location != HT_SB_UNKNOWN) {
|
|
SendNotifyMessage ((HWND)pWin, MSG_VSCROLL, sbCode, y);
|
|
SetAutoRepeatMessage ((HWND)pWin, MSG_VSCROLL, sbCode, y);
|
|
}
|
|
break;
|
|
|
|
case MSG_NCLBUTTONUP:
|
|
if (sbCode == SB_THUMBTRACK
|
|
&& downPos == HT_SB_VTHUMB) {
|
|
newBarStart = oldBarStart + y - oldy;
|
|
if (RECTH(rcBar) != 0)
|
|
newThumbPos = CALC_THUMB_VPOS(newBarStart, rcBar, pWin->vscroll);
|
|
|
|
pWin->vscroll.status &= ~SBS_PRESSED_LTUP;
|
|
pWin->vscroll.status &= ~SBS_PRESSED_BTDN;
|
|
|
|
if (newThumbPos < pWin->vscroll.minPos)
|
|
newThumbPos = pWin->vscroll.minPos;
|
|
if (newThumbPos > pWin->vscroll.maxPos)
|
|
newThumbPos = pWin->vscroll.maxPos;
|
|
if (newBarStart != oldBarStart) {
|
|
SendNotifyMessage ((HWND)pWin,
|
|
MSG_VSCROLL, SB_THUMBPOSITION, newThumbPos);
|
|
}
|
|
|
|
// wndDrawNCButton (pWin, downPos, LFRDR_BTN_STATUS_NORMAL);
|
|
wndDrawNCButton (pWin, HT_VSCROLL, 0);
|
|
|
|
downPos = HT_SB_UNKNOWN;
|
|
movePos = HT_SB_UNKNOWN;
|
|
hilitePos = HT_SB_UNKNOWN;
|
|
return -1;
|
|
}
|
|
|
|
if (downPos != HT_SB_UNKNOWN) {
|
|
//wndDrawNCButton (pWin, downPos, LFRDR_BTN_STATUS_NORMAL);
|
|
wndDrawNCButton (pWin, HT_VSCROLL, 0);
|
|
SendNotifyMessage ((HWND)pWin, MSG_VSCROLL, SB_ENDSCROLL, 0);
|
|
/* cancel repeat message */
|
|
SetAutoRepeatMessage (0, 0, 0, 0);
|
|
}
|
|
|
|
downPos = HT_SB_UNKNOWN;
|
|
movePos = HT_SB_UNKNOWN;
|
|
hilitePos = HT_SB_UNKNOWN;
|
|
return -1;
|
|
|
|
case MSG_NCMOUSEMOVE:
|
|
if (sbCode == SB_THUMBTRACK
|
|
&& downPos == HT_SB_VTHUMB) {
|
|
newBarStart = oldBarStart + y - oldy;
|
|
if (RECTH(rcBar) != 0)
|
|
newThumbPos = CALC_THUMB_VPOS(newBarStart, rcBar, pWin->vscroll);
|
|
|
|
if (newThumbPos < pWin->vscroll.minPos)
|
|
newThumbPos = pWin->vscroll.minPos;
|
|
if (newThumbPos > (1 + pWin->vscroll.maxPos - pWin->vscroll.pageStep))
|
|
newThumbPos = pWin->vscroll.maxPos - pWin->vscroll.pageStep + 1;
|
|
if (newThumbPos != oldThumbPos) {
|
|
if (pWin->vscroll.pageStep < pWin->vscroll.maxPos
|
|
- pWin->vscroll.minPos + 1)
|
|
{
|
|
SendNotifyMessage ((HWND)pWin,
|
|
MSG_VSCROLL, SB_THUMBTRACK, newThumbPos);
|
|
oldThumbPos = newThumbPos;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (downPos != HT_SB_UNKNOWN) {
|
|
if (movePos == downPos && location != downPos)
|
|
wndDrawNCButton (pWin, downPos, LFRDR_BTN_STATUS_NORMAL);
|
|
else if (movePos != downPos && location == downPos)
|
|
wndDrawNCButton (pWin, downPos, LFRDR_BTN_STATUS_PRESSED);
|
|
movePos = location;
|
|
}
|
|
else {
|
|
PostMessage((HWND)pWin, MSG_NCSETCURSOR, location, MAKELONG (x, y));
|
|
|
|
if (hilitePos != location) {
|
|
if (hilitePos != HT_SB_UNKNOWN)
|
|
wndDrawNCButton (pWin, hilitePos, LFRDR_BTN_STATUS_NORMAL);
|
|
|
|
if ((location != HT_SB_UNKNOWN)
|
|
&& ((location & HT_SB_VMASK) == HT_SB_VMASK))
|
|
wndDrawNCButton (pWin, location, LFRDR_BTN_STATUS_HILITE);
|
|
}
|
|
if ((location & HT_SB_VMASK) == HT_SB_VMASK)
|
|
hilitePos = set_hilite_sbpos (location);
|
|
else
|
|
hilitePos = HT_SB_UNKNOWN;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void wndHandleCustomHotspot (PMAINWIN pWin,
|
|
int message, int location, int x, int y)
|
|
{
|
|
const WINDOW_ELEMENT_RENDERER *rdr;
|
|
static int downPos = HT_UNKNOWN;
|
|
static int movePos = HT_UNKNOWN;
|
|
static int hilitePos = HT_UNKNOWN;
|
|
RECT rc;
|
|
HDC hdc;
|
|
|
|
rdr = GetWindowInfo ((HWND)pWin)->we_rdr;
|
|
|
|
if (rdr->calc_we_area ((HWND)pWin, location, &rc))
|
|
return;
|
|
|
|
switch (message) {
|
|
case MSG_NCLBUTTONDOWN:
|
|
downPos = location;
|
|
movePos = location;
|
|
hilitePos = HT_UNKNOWN;
|
|
|
|
hdc = get_valid_dc (pWin, FALSE);
|
|
if (rdr->draw_custom_hotspot)
|
|
rdr->draw_custom_hotspot ((HWND)pWin, hdc, location,
|
|
LFRDR_BTN_STATUS_PRESSED);
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, rdr, hdc, location);
|
|
}
|
|
release_valid_dc (pWin, hdc);
|
|
|
|
if (rdr->on_click_hotspot)
|
|
rdr->on_click_hotspot ((HWND)pWin, location);
|
|
break;
|
|
|
|
case MSG_NCLBUTTONUP:
|
|
hdc = get_valid_dc (pWin, FALSE);
|
|
if (rdr->draw_custom_hotspot && (downPos != HT_UNKNOWN)) {
|
|
rdr->draw_custom_hotspot ((HWND)pWin, hdc, location,
|
|
LFRDR_BTN_STATUS_NORMAL);
|
|
}
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, rdr, hdc, location);
|
|
}
|
|
release_valid_dc (pWin, hdc);
|
|
|
|
downPos = HT_UNKNOWN;
|
|
movePos = HT_UNKNOWN;
|
|
hilitePos = HT_UNKNOWN;
|
|
break;
|
|
|
|
case MSG_NCMOUSEMOVE:
|
|
hdc = get_valid_dc (pWin, FALSE);
|
|
if (downPos != HT_UNKNOWN) {
|
|
if (rdr->draw_custom_hotspot) {
|
|
if (movePos == downPos && location != downPos)
|
|
rdr->draw_custom_hotspot ((HWND)pWin, hdc, location,
|
|
LFRDR_BTN_STATUS_NORMAL);
|
|
else if (movePos != downPos && location == downPos)
|
|
rdr->draw_custom_hotspot ((HWND)pWin, hdc, location,
|
|
LFRDR_BTN_STATUS_PRESSED);
|
|
}
|
|
movePos = location;
|
|
}
|
|
else {
|
|
PostMessage((HWND)pWin,
|
|
MSG_NCSETCURSOR, location, MAKELONG (x, y));
|
|
|
|
if (rdr->draw_custom_hotspot && (hilitePos != location)) {
|
|
if (hilitePos != HT_UNKNOWN)
|
|
rdr->draw_custom_hotspot ((HWND)pWin, hdc, location,
|
|
LFRDR_BTN_STATUS_NORMAL);
|
|
|
|
if (location != HT_UNKNOWN)
|
|
rdr->draw_custom_hotspot ((HWND)pWin, hdc, location,
|
|
LFRDR_BTN_STATUS_HILITE);
|
|
}
|
|
hilitePos = location;
|
|
}
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, rdr, hdc, location);
|
|
}
|
|
release_valid_dc (pWin, hdc);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* this function is CONTROL safe. */
|
|
static LRESULT DefaultNCMouseMsgHandler(PMAINWIN pWin, UINT message,
|
|
int location, int x, int y)
|
|
{
|
|
static int downCode = HT_UNKNOWN;
|
|
static int moveCode = HT_UNKNOWN;
|
|
static int hiliteCode = HT_UNKNOWN;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
int barItem;
|
|
#endif
|
|
|
|
/*for user hittest process*/
|
|
if (location & HT_USER_MASK) {
|
|
wndHandleCustomHotspot (pWin, message, location, x, y);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (pWin->WinType == TYPE_MAINWIN && message == MSG_NCMOUSEMOVE)
|
|
wndTrackMenuBarOnMouseMove (pWin, message, location, x, y);
|
|
#endif
|
|
|
|
/*process scrollbar*/
|
|
if (pWin->dwStyle & WS_HSCROLL) {
|
|
switch (wndHandleHScrollBar (pWin, message, location, x, y)) {
|
|
case 1:
|
|
return 0;
|
|
case -1:
|
|
downCode = HT_UNKNOWN;
|
|
moveCode = HT_UNKNOWN;
|
|
return 0;
|
|
/* hscroll do not response this message.*/
|
|
case 0:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pWin->dwStyle & WS_VSCROLL) {
|
|
switch (wndHandleVScrollBar (pWin, message, location, x, y)) {
|
|
case 1:
|
|
return 0;
|
|
case -1:
|
|
downCode = HT_UNKNOWN;
|
|
moveCode = HT_UNKNOWN;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
switch (message) {
|
|
case MSG_NCLBUTTONDOWN:
|
|
#ifdef _MGHAVE_MENU
|
|
if (location == HT_MENUBAR) {
|
|
barItem = MenuBarHitTest ((HWND)pWin, x, y);
|
|
if (barItem >= 0)
|
|
TrackMenuBar ((HWND)pWin, barItem);
|
|
|
|
return 0;
|
|
}
|
|
else
|
|
#endif
|
|
if (location & HT_DRAGGABLE && !(pWin->dwExStyle & WS_EX_NOTDRAGGABLE)) {
|
|
DRAGINFO drag_info;
|
|
|
|
drag_info.location = location;
|
|
drag_info.init_x = x;
|
|
drag_info.init_y = y;
|
|
SendMessage (HWND_DESKTOP, MSG_STARTDRAGWIN,
|
|
(WPARAM)pWin, (LPARAM)&drag_info);
|
|
}
|
|
else {
|
|
downCode = location;
|
|
moveCode = location;
|
|
hiliteCode = HT_UNKNOWN;
|
|
|
|
wndDrawNCButton (pWin, downCode, LFRDR_BTN_STATUS_PRESSED);
|
|
}
|
|
break;
|
|
|
|
case MSG_NCMOUSEMOVE:
|
|
if (pWin->hOldUnderPointer && location == HT_OUT) {
|
|
PostMessage (pWin->hOldUnderPointer,
|
|
MSG_MOUSEMOVEIN, FALSE, 0);
|
|
PostMessage (pWin->hOldUnderPointer,
|
|
MSG_NCMOUSEMOVE, HT_OUT, MAKELONG (x, y));
|
|
pWin->hOldUnderPointer = 0;
|
|
}
|
|
|
|
if (downCode != HT_UNKNOWN) {
|
|
if (moveCode == downCode && location != downCode) {
|
|
wndDrawNCButton (pWin, downCode, LFRDR_BTN_STATUS_NORMAL);
|
|
moveCode = location;
|
|
}
|
|
else if (moveCode != downCode && location == downCode) {
|
|
wndDrawNCButton (pWin, downCode, LFRDR_BTN_STATUS_PRESSED);
|
|
moveCode = location;
|
|
}
|
|
}
|
|
else {
|
|
/*only move process*/
|
|
if (hiliteCode != location) {
|
|
if (hiliteCode != HT_SB_UNKNOWN)
|
|
wndDrawNCButton (pWin, hiliteCode, LFRDR_BTN_STATUS_NORMAL);
|
|
|
|
wndDrawNCButton (pWin, location, LFRDR_BTN_STATUS_HILITE);
|
|
}
|
|
hiliteCode = location;
|
|
}
|
|
|
|
if (location != HT_CLIENT && downCode == HT_UNKNOWN) {
|
|
PostMessage((HWND)pWin, MSG_NCSETCURSOR,
|
|
location, MAKELONG (x, y));
|
|
}
|
|
break;
|
|
|
|
case MSG_NCLBUTTONUP:
|
|
if (downCode & HT_DRAGGABLE && !(pWin->dwExStyle & WS_EX_NOTDRAGGABLE)) {
|
|
SendMessage (HWND_DESKTOP, MSG_CANCELDRAGWIN, (WPARAM)pWin, 0L);
|
|
}
|
|
else if (location == downCode) {
|
|
wndDrawNCButton (pWin, downCode, LFRDR_BTN_STATUS_HILITE);
|
|
switch (location) {
|
|
case HT_CLOSEBUTTON:
|
|
SendNotifyMessage ((HWND)pWin, MSG_CLOSE, 0, 0);
|
|
break;
|
|
|
|
case HT_MAXBUTTON:
|
|
SendNotifyMessage ((HWND)pWin, MSG_MAXIMIZE, 0, 0);
|
|
break;
|
|
|
|
case HT_MINBUTTON:
|
|
SendNotifyMessage ((HWND)pWin, MSG_MINIMIZE, 0, 0);
|
|
break;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
case HT_ICON:
|
|
if (pWin->hSysMenu)
|
|
TrackPopupMenu (pWin->hSysMenu,
|
|
TPM_SYSCMD, x, y, (HWND)pWin);
|
|
break;
|
|
#endif
|
|
|
|
case HT_CAPTION:
|
|
break;
|
|
|
|
}
|
|
}
|
|
downCode = HT_UNKNOWN;
|
|
moveCode = HT_UNKNOWN;
|
|
hiliteCode = HT_UNKNOWN;
|
|
break;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
case MSG_NCRBUTTONUP:
|
|
if (location == HT_CAPTION && pWin->hSysMenu)
|
|
TrackPopupMenu (pWin->hSysMenu, TPM_SYSCMD, x, y, (HWND)pWin);
|
|
break;
|
|
#endif
|
|
|
|
case MSG_NCLBUTTONDBLCLK:
|
|
if (location == HT_ICON)
|
|
SendNotifyMessage ((HWND)pWin, MSG_CLOSE, 0, 0);
|
|
/* else if (location == HT_CAPTION) */
|
|
/* SendNotifyMessage ((HWND)pWin, MSG_MAXIMIZE, 0, 0); */
|
|
break;
|
|
|
|
/* case MSG_NCRBUTTONDOWN: */
|
|
/* case MSG_NCRBUTTONDBLCLK: */
|
|
/* break; */
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT DefaultKeyMsgHandler (PMAINWIN pWin, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
/*
|
|
** NOTE:
|
|
** Currently only handle one message.
|
|
** Should handle fowllowing messages:
|
|
**
|
|
** MSG_KEYDOWN,
|
|
** MSG_KEYUP,
|
|
** MSG_CHAR,
|
|
** MSG_SYSKEYDOWN,
|
|
** MSG_SYSCHAR.
|
|
*/
|
|
if (message == MSG_KEYDOWN
|
|
|| message == MSG_KEYUP
|
|
|| message == MSG_KEYLONGPRESS
|
|
|| message == MSG_KEYALWAYSPRESS
|
|
|| message == MSG_CHAR) {
|
|
if (pWin->hActiveChild
|
|
&& !(pWin->dwStyle & WS_DISABLED)) {
|
|
/* DK[07/05/10]Fix Bug4798, Check the control if has WS_DISABLED property. */
|
|
PCONTROL pChild = (PCONTROL) pWin->hActiveChild;
|
|
if (!(pChild->dwStyle & WS_DISABLED))
|
|
SendMessage (pWin->hActiveChild, message, wParam, lParam);
|
|
}
|
|
}
|
|
#ifdef _MGHAVE_MENU
|
|
else if (message == MSG_SYSKEYUP) {
|
|
if (pWin->WinType == TYPE_MAINWIN
|
|
&& !(pWin->dwStyle & WS_DISABLED))
|
|
TrackMenuBar ((HWND)pWin, 0);
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT DefaultCreateMsgHandler(PMAINWIN pWin, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
|
|
/*
|
|
** NOTE:
|
|
** Currently does nothing.
|
|
** Should handle fowllowing messages:
|
|
**
|
|
** MSG_NCCREATE,
|
|
** MSG_CREATE,
|
|
** MSG_INITPANES,
|
|
** MSG_DESTROYPANES,
|
|
** MSG_DESTROY,
|
|
** MSG_NCDESTROY.
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
static void RecalcScrollInfo (PMAINWIN pWin, BOOL bIsHBar)
|
|
{
|
|
PLFSCROLLBARINFO pSBar;
|
|
const WINDOWINFO *info = GetWindowInfo ((HWND)pWin);
|
|
|
|
if (bIsHBar)
|
|
pSBar = &pWin->hscroll;
|
|
else
|
|
pSBar = &pWin->vscroll;
|
|
|
|
if (pSBar->minPos == pSBar->maxPos) {
|
|
ShowScrollBar((HWND)pWin, bIsHBar, FALSE);
|
|
return;
|
|
}
|
|
|
|
info->we_rdr->calc_thumb_area ((HWND)pWin, !bIsHBar, pSBar);
|
|
}
|
|
|
|
/* This function is CONTROL safe. */
|
|
static void
|
|
OnChangeSize (PMAINWIN pWin, PRECT pDestRect, PRECT pResultRect)
|
|
{
|
|
RECT cli_rc;
|
|
const WINDOWINFO *info = GetWindowInfo ((HWND)pWin);
|
|
int w, h;
|
|
|
|
if (pDestRect) {
|
|
int minWidth = 0, minHeight = 0;
|
|
|
|
memcpy(&pWin->left, pDestRect, sizeof(RECT));
|
|
|
|
minWidth =
|
|
info->we_rdr->calc_we_metrics ((HWND)pWin, NULL,
|
|
LFRDR_METRICS_MINWIN_WIDTH);
|
|
|
|
minHeight =
|
|
info->we_rdr->calc_we_metrics ((HWND)pWin, NULL,
|
|
LFRDR_METRICS_MINWIN_HEIGHT);
|
|
|
|
if ((minHeight > (pWin->bottom - pWin->top))
|
|
&& (pWin->bottom != pWin->top))
|
|
pWin->bottom = pWin->top + minHeight;
|
|
|
|
if ((pWin->right < (pWin->left + minWidth))
|
|
&& (pWin->right != pWin->left))
|
|
pWin->right = pWin->left + minWidth;
|
|
|
|
if (pResultRect)
|
|
memcpy (pResultRect, &pWin->left, sizeof(RECT));
|
|
}
|
|
|
|
memcpy (&pWin->cl, &pWin->left, sizeof(RECT));
|
|
|
|
info->we_rdr->calc_we_area ((HWND)pWin, HT_CLIENT, &cli_rc);
|
|
pWin->cl += cli_rc.left;
|
|
pWin->ct += cli_rc.top;
|
|
|
|
if ((w = RECTW(cli_rc)) > 0)
|
|
pWin->cr = pWin->cl + w;
|
|
else
|
|
pWin->cr = pWin->cl;
|
|
|
|
if ((h = RECTH(cli_rc)) > 0)
|
|
pWin->cb = pWin->ct + h;
|
|
else
|
|
pWin->cb = pWin->ct;
|
|
|
|
if (pWin->dwStyle & WS_HSCROLL && !(pWin->hscroll.status & SBS_HIDE)) {
|
|
RecalcScrollInfo (pWin, TRUE);
|
|
}
|
|
|
|
if (pWin->dwStyle & WS_VSCROLL && !(pWin->vscroll.status & SBS_HIDE)) {
|
|
RecalcScrollInfo (pWin, FALSE);
|
|
}
|
|
}
|
|
|
|
static void OnQueryNCRect(PMAINWIN pWin, PRECT pRC)
|
|
{
|
|
memcpy(pRC, &pWin->left, sizeof(RECT));
|
|
}
|
|
|
|
static void OnQueryClientArea(PMAINWIN pWin, PRECT pRC)
|
|
{
|
|
memcpy(pRC, &pWin->cl, sizeof(RECT));
|
|
}
|
|
|
|
static void
|
|
calc_metrics_cli2win (const WINDOW_ELEMENT_RENDERER *rdr,
|
|
int dwStyle, int win_type, int* width, int* height,
|
|
BOOL hasMenu)
|
|
{
|
|
int iBorder = 0;
|
|
LFRDR_WINSTYLEINFO info;
|
|
|
|
if (!width && !height)
|
|
return;
|
|
|
|
info.dwStyle = dwStyle;
|
|
info.winType = win_type;
|
|
|
|
if (dwStyle & WS_BORDER || dwStyle & WS_THINFRAME
|
|
|| dwStyle & WS_THICKFRAME) {
|
|
iBorder =
|
|
rdr->calc_we_metrics (HWND_NULL, &info, LFRDR_METRICS_BORDER);
|
|
}
|
|
|
|
if (width)
|
|
{
|
|
*width += iBorder <<1;
|
|
|
|
if (dwStyle & WS_VSCROLL) {
|
|
*width +=
|
|
rdr->calc_we_metrics (HWND_NULL, &info, LFRDR_METRICS_VSCROLL_W);
|
|
}
|
|
}
|
|
|
|
if (height)
|
|
{
|
|
*height += iBorder <<1;
|
|
|
|
if (dwStyle & WS_CAPTION) {
|
|
*height +=
|
|
rdr->calc_we_metrics (HWND_NULL, &info, LFRDR_METRICS_CAPTION_H);
|
|
}
|
|
|
|
if (dwStyle & WS_HSCROLL) {
|
|
*height +=
|
|
rdr->calc_we_metrics (HWND_NULL, &info, LFRDR_METRICS_VSCROLL_W);
|
|
}
|
|
|
|
if (hasMenu)
|
|
*height +=
|
|
rdr->calc_we_metrics (HWND_NULL, &info, LFRDR_METRICS_MENU_H);
|
|
}
|
|
}
|
|
|
|
int GUIAPI ClientWidthToWindowWidthEx (DWORD dwStyle, int win_type, int cw)
|
|
{
|
|
int width = cw;
|
|
const WINDOW_ELEMENT_RENDERER* rdr =
|
|
GetDefaultWindowElementRenderer ();
|
|
|
|
calc_metrics_cli2win (rdr, dwStyle, win_type, &width,
|
|
NULL, FALSE);
|
|
|
|
return width;
|
|
}
|
|
|
|
int GUIAPI ClientHeightToWindowHeightEx (DWORD dwStyle, int win_type,
|
|
int ch, BOOL hasMenu)
|
|
{
|
|
int height = ch;
|
|
const WINDOW_ELEMENT_RENDERER* rdr =
|
|
GetDefaultWindowElementRenderer ();
|
|
|
|
calc_metrics_cli2win (rdr, dwStyle, win_type, NULL,
|
|
&height, hasMenu);
|
|
|
|
return height;
|
|
}
|
|
|
|
|
|
BOOL GUIAPI AdjustWindowRectEx (RECT* pRect, DWORD dwStyle,
|
|
BOOL bMenu, DWORD dwExStyle)
|
|
{
|
|
int cw, ch;
|
|
int ww, wh;
|
|
int off_x, off_y;
|
|
int minw, minh;
|
|
//for minimum window
|
|
LFRDR_WINSTYLEINFO style_info;
|
|
WINDOW_ELEMENT_RENDERER* rdr;
|
|
|
|
if (pRect == NULL)
|
|
return FALSE;
|
|
|
|
cw = RECTWP (pRect);
|
|
ch = RECTHP (pRect);
|
|
|
|
ww = ClientWidthToWindowWidthEx (dwStyle, LFRDR_WINTYPE_MAINWIN, cw);
|
|
wh = ClientHeightToWindowHeightEx (dwStyle, LFRDR_WINTYPE_MAINWIN, ch, bMenu);
|
|
|
|
off_x = (ww - cw) >> 1;
|
|
off_y = (wh - ch) >> 1;
|
|
|
|
pRect->left -= off_x;
|
|
pRect->right += off_x + ((ww - cw) % 2);
|
|
pRect->top -= off_y;
|
|
pRect->bottom += off_y + ((wh - ch) % 2);
|
|
|
|
//limit the minimum window size
|
|
rdr = (WINDOW_ELEMENT_RENDERER*)GetDefaultWindowElementRenderer ();
|
|
if (rdr) {
|
|
style_info.dwStyle = dwStyle;
|
|
style_info.winType = LFRDR_WINTYPE_MAINWIN;
|
|
minw = rdr->calc_we_metrics(0, &style_info, LFRDR_METRICS_MINWIN_WIDTH);
|
|
minh = rdr->calc_we_metrics(0, &style_info, LFRDR_METRICS_MINWIN_HEIGHT);
|
|
|
|
if (ww < minw) {
|
|
pRect->right += minw - ww;
|
|
}
|
|
if (wh < minh) {
|
|
pRect->bottom += minh - wh;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* this function is CONTROL safe. */
|
|
static int HittestOnNClient (PMAINWIN pWin, int x, int y)
|
|
{
|
|
const WINDOWINFO *info = GetWindowInfo ((HWND)pWin);
|
|
return info->we_rdr->hit_test ((HWND)pWin, x, y);
|
|
}
|
|
|
|
|
|
/************************** internal functions *********************************/
|
|
void gui_WndRect(HWND hWnd, PRECT prc)
|
|
{
|
|
PCONTROL pParent;
|
|
PCONTROL pCtrl;
|
|
|
|
pParent = pCtrl = (PCONTROL) hWnd;
|
|
|
|
if (hWnd == HWND_DESKTOP) {
|
|
*prc = g_rcScr;
|
|
return;
|
|
}
|
|
|
|
prc->left = pCtrl->left;
|
|
prc->top = pCtrl->top;
|
|
prc->right = pCtrl->right;
|
|
prc->bottom = pCtrl->bottom;
|
|
|
|
/* dongjunjie 2009/7/9 main window and control as main window
|
|
* don't need offset
|
|
* */
|
|
if (pCtrl->WinType == TYPE_MAINWIN)
|
|
return ;
|
|
|
|
while ((pParent = pParent->pParent)) {
|
|
prc->left += pParent->cl;
|
|
prc->top += pParent->ct;
|
|
prc->right += pParent->cl;
|
|
prc->bottom += pParent->ct;
|
|
}
|
|
}
|
|
|
|
void gui_WndClientRect(HWND hWnd, PRECT prc)
|
|
{
|
|
PCONTROL pCtrl;
|
|
PCONTROL pParent;
|
|
pParent = pCtrl = (PCONTROL) hWnd;
|
|
|
|
if (hWnd == HWND_DESKTOP) {
|
|
*prc = g_rcScr;
|
|
return;
|
|
}
|
|
|
|
prc->left = pCtrl->cl;
|
|
prc->top = pCtrl->ct;
|
|
prc->right = pCtrl->cr;
|
|
prc->bottom = pCtrl->cb;
|
|
while ((pParent = pParent->pParent)) {
|
|
prc->left += pParent->cl;
|
|
prc->top += pParent->ct;
|
|
prc->right += pParent->cl;
|
|
prc->bottom += pParent->ct;
|
|
}
|
|
}
|
|
|
|
extern HWND __mg_ime_wnd;
|
|
void __gui_open_ime_window (PMAINWIN pWin, BOOL open_close, HWND rev_hwnd)
|
|
{
|
|
#ifndef _MGRM_PROCESSES
|
|
if (__mg_ime_wnd && pWin) {
|
|
int edit_status;
|
|
|
|
if (pWin->pMainWin && ((pWin->pMainWin->dwExStyle & WS_EX_TOOLWINDOW)
|
|
|| ((HWND)(pWin->pMainWin) == __mg_ime_wnd)))
|
|
return;
|
|
|
|
edit_status = SendAsyncMessage ((HWND)pWin, MSG_DOESNEEDIME, 0, 0L);
|
|
if ((edit_status == IME_WINDOW_TYPE_EDITABLE
|
|
|| edit_status == IME_WINDOW_TYPE_PASSWORD)
|
|
&& open_close) {
|
|
SendNotifyMessage (__mg_ime_wnd, MSG_IME_OPEN, 0, 0);
|
|
}
|
|
else {
|
|
SendNotifyMessage (__mg_ime_wnd, MSG_IME_CLOSE, 0, 0);
|
|
}
|
|
}
|
|
#else
|
|
if (!mgIsServer && pWin) {
|
|
BOOL edit_status;
|
|
REQUEST req;
|
|
BOOL open = FALSE;
|
|
|
|
if (pWin->pMainWin && (pWin->pMainWin->dwExStyle & WS_EX_TOOLWINDOW))
|
|
return;
|
|
|
|
edit_status = SendAsyncMessage ((HWND)pWin, MSG_DOESNEEDIME, 0, 0L);
|
|
|
|
req.id = REQID_OPENIMEWND;
|
|
req.data = &open;
|
|
req.len_data = sizeof (BOOL);
|
|
if ((edit_status == IME_WINDOW_TYPE_EDITABLE
|
|
|| edit_status == IME_WINDOW_TYPE_PASSWORD)
|
|
&& open_close) {
|
|
open = TRUE;
|
|
}
|
|
ClientRequest (&req, NULL, 0);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static LRESULT DefaultPostMsgHandler(PMAINWIN pWin, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message) {
|
|
case MSG_SETCURSOR:
|
|
/*
|
|
** NOTE:
|
|
** this message is only implemented for main window.
|
|
** for CONTROL, must handle this message and should NOT
|
|
** call default window procedure
|
|
** when handle MSG_SETCURSOR.
|
|
*/
|
|
if (wndMouseInWhichControl (pWin, LOSWORD(lParam), HISWORD(lParam),
|
|
NULL))
|
|
break;
|
|
|
|
if (pWin->hCursor)
|
|
SetCursor(pWin->hCursor);
|
|
break;
|
|
|
|
case MSG_NCSETCURSOR:
|
|
/*
|
|
** NOTE:
|
|
** this message is only implemented for main window.
|
|
** for CONTROL, must handle this message and should NOT
|
|
** call default window procedure
|
|
** when handle MSG_SETCURSOR.
|
|
*/
|
|
switch (wParam) {
|
|
case HT_BORDER_TOP:
|
|
case HT_BORDER_BOTTOM:
|
|
SetCursor (GetSystemCursor (IDC_SIZENS));
|
|
break;
|
|
case HT_BORDER_LEFT:
|
|
case HT_BORDER_RIGHT:
|
|
SetCursor (GetSystemCursor (IDC_SIZEWE));
|
|
break;
|
|
case HT_CORNER_TL:
|
|
case HT_CORNER_BR:
|
|
SetCursor (GetSystemCursor (IDC_SIZENWSE));
|
|
break;
|
|
case HT_CORNER_BL:
|
|
case HT_CORNER_TR:
|
|
SetCursor (GetSystemCursor (IDC_SIZENESW));
|
|
break;
|
|
default:
|
|
SetCursor (GetSystemCursor (IDC_ARROW));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case MSG_HITTEST:
|
|
if (PtInRect ((PRECT)(&(pWin->cl)), (int)wParam, (int)lParam))
|
|
return HT_CLIENT;
|
|
else {
|
|
CONTROL * pCtrl;
|
|
if (pWin->WinType == TYPE_MAINWIN &&
|
|
(pCtrl= (CONTROL*)(pWin->hFirstChildAsMainWin)) != NULL) {
|
|
int x = (int)wParam;
|
|
int y = (int)lParam;
|
|
ScreenToClient((HWND)pCtrl->pParent,&x,&y);
|
|
|
|
while (pCtrl) {
|
|
if ((pCtrl->dwStyle&WS_VISIBLE) &&
|
|
PtInRect((PRECT)&(pCtrl->cl),x, y)) {
|
|
return HT_CLIENT;
|
|
}
|
|
pCtrl = pCtrl->next_ctrl_as_main;
|
|
}
|
|
}
|
|
return HittestOnNClient (pWin, (int)wParam, (int)lParam);
|
|
}
|
|
break;
|
|
|
|
case MSG_CHANGESIZE:
|
|
OnChangeSize (pWin, (PRECT)wParam, (PRECT)lParam);
|
|
RecalcClientArea ((HWND)pWin);
|
|
break;
|
|
|
|
case MSG_SIZECHANGING:
|
|
memcpy ((PRECT)lParam, (PRECT)wParam, sizeof (RECT));
|
|
break;
|
|
|
|
case MSG_QUERYNCRECT:
|
|
OnQueryNCRect(pWin, (PRECT)lParam);
|
|
break;
|
|
|
|
case MSG_QUERYCLIENTAREA:
|
|
OnQueryClientArea(pWin, (PRECT)lParam);
|
|
break;
|
|
|
|
case MSG_SETFOCUS:
|
|
case MSG_KILLFOCUS:
|
|
if (pWin->hActiveChild && !lParam)
|
|
SendNotifyMessage (pWin->hActiveChild, message, 0, lParam);
|
|
break;
|
|
|
|
case MSG_MOUSEACTIVE:
|
|
if (pWin->WinType == TYPE_CONTROL
|
|
&& !(pWin->dwStyle & WS_DISABLED)) {
|
|
|
|
if (wParam != HT_OUT) {
|
|
PCONTROL pCtrl = (PCONTROL)pWin;
|
|
PCONTROL old_active = pCtrl->pParent->active;
|
|
|
|
if (old_active != (PCONTROL)pWin) {
|
|
if (old_active) {
|
|
SendNotifyMessage ((HWND)old_active,
|
|
MSG_ACTIVE, FALSE, wParam);
|
|
SendNotifyMessage ((HWND)old_active,
|
|
MSG_KILLFOCUS, (WPARAM)pWin, 0);
|
|
}
|
|
|
|
pCtrl->pParent->active = (PCONTROL)pWin;
|
|
|
|
SendNotifyMessage ((HWND)pWin, MSG_ACTIVE, TRUE, 0);
|
|
SendNotifyMessage ((HWND)pWin,
|
|
MSG_SETFOCUS, (WPARAM)old_active, 0);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MSG_WINDOWDROPPED: {
|
|
RECT rc;
|
|
rc.left = LOSWORD (wParam);
|
|
rc.top = HISWORD (wParam);
|
|
rc.right = LOSWORD (lParam);
|
|
rc.bottom = HISWORD (lParam);
|
|
|
|
MoveWindow ((HWND)pWin, rc.left, rc.top,
|
|
RECTW(rc), RECTH(rc), FALSE);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void wndEraseBackground(const PMAINWIN pWin,
|
|
HDC hdc, const RECT* pClipRect)
|
|
{
|
|
RECT rcTemp;
|
|
BOOL fGetDC = FALSE;
|
|
const WINDOW_ELEMENT_RENDERER *rdr =
|
|
GetWindowInfo ((HWND)pWin)->we_rdr;
|
|
|
|
if (hdc == 0) {
|
|
hdc = get_valid_dc ((PMAINWIN)pWin, TRUE);
|
|
fGetDC = TRUE;
|
|
}
|
|
|
|
if (pClipRect) {
|
|
rcTemp = *pClipRect;
|
|
#if 0
|
|
if (pWin->WinType == TYPE_MAINWIN) {
|
|
ScreenToClient ((HWND)pWin, &rcTemp.left, &rcTemp.top);
|
|
ScreenToClient ((HWND)pWin, &rcTemp.right, &rcTemp.bottom);
|
|
}
|
|
#endif
|
|
}
|
|
else {
|
|
rcTemp.left = rcTemp.top = 0;
|
|
rcTemp.right = pWin->cr - pWin->cl;
|
|
rcTemp.bottom = pWin->cb - pWin->ct;
|
|
}
|
|
|
|
|
|
if (rdr->erase_background)
|
|
rdr->erase_background ((HWND)pWin, hdc, &rcTemp);
|
|
|
|
/* do secondaryDC update when EndPaint().*/
|
|
#if 0
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
HDC real_dc = HDC_INVALID;
|
|
real_dc = GetClientDC ((HWND)pWin->pMainWin);
|
|
__mg_update_secondary_dc ((PMAINWIN)pWin, hdc, real_dc, &rcTemp, HT_CLIENT);
|
|
ReleaseDC (real_dc);
|
|
}
|
|
#endif
|
|
|
|
if (fGetDC) {
|
|
release_valid_dc ((PMAINWIN)pWin, hdc);
|
|
}
|
|
}
|
|
|
|
/* this function is CONTROL safe. */
|
|
static void wndDrawNCFrame(MAINWIN* pWin, HDC hdc, const RECT* prcInvalid)
|
|
{
|
|
BOOL fGetDC = FALSE;
|
|
const WINDOW_ELEMENT_RENDERER *rdr;
|
|
BOOL is_active = TRUE;
|
|
|
|
/* to avoid some unexpected event... */
|
|
if (!MG_IS_WINDOW ((HWND)pWin))
|
|
return;
|
|
|
|
if (hdc == 0) {
|
|
hdc = get_valid_dc (pWin, FALSE);
|
|
fGetDC = TRUE;
|
|
}
|
|
|
|
if (prcInvalid)
|
|
ClipRectIntersect (hdc, prcInvalid);
|
|
|
|
rdr = GetWindowInfo ((HWND)pWin)->we_rdr;
|
|
|
|
/*fix bug 3099: GetActiveWindow can not use in control.*/
|
|
if (pWin->WinType == TYPE_MAINWIN)
|
|
is_active = !(pWin->dwStyle & WS_DISABLED) &&
|
|
(GetActiveWindow() == (HWND)pWin);
|
|
else {
|
|
/*
|
|
is_active = !(pWin->dwStyle & WS_DISABLED) &&
|
|
(((PCONTROL)pWin)->pParent->active == (PCONTROL)pWin);
|
|
*/
|
|
}
|
|
|
|
RecalcScrollInfo (pWin, TRUE);
|
|
RecalcScrollInfo (pWin, FALSE);
|
|
|
|
rdr->draw_caption ((HWND)pWin, hdc, is_active);
|
|
if (is_active)
|
|
rdr->draw_caption_button ((HWND)pWin, hdc, 0, LFRDR_BTN_STATUS_NORMAL);
|
|
else
|
|
rdr->draw_caption_button ((HWND)pWin, hdc, 0, LFRDR_BTN_STATUS_INACTIVE);
|
|
|
|
/*dongjunjie 09/07/09
|
|
* If Border is Zero, but MainWindow style have caption
|
|
* we should notify the secondaryDC
|
|
* */
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, rdr, hdc, HT_CAPTION);
|
|
}
|
|
|
|
if (!(pWin->hscroll.status & SBS_HIDE)) {
|
|
wndDrawNCButtonEx (pWin, hdc, HT_HSCROLL, 0);
|
|
}
|
|
|
|
if (!(pWin->vscroll.status & SBS_HIDE)) {
|
|
wndDrawNCButtonEx (pWin, hdc, HT_VSCROLL, 0);
|
|
}
|
|
|
|
if (rdr->draw_custom_hotspot)
|
|
rdr->draw_custom_hotspot ((HWND)pWin, hdc, 0, 0);
|
|
|
|
rdr->draw_border ((HWND)pWin, hdc, is_active);
|
|
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, rdr, hdc, HT_BORDER);
|
|
}
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (pWin->WinType == TYPE_MAINWIN) {
|
|
DrawMenuBarHelper (pWin, hdc, prcInvalid);
|
|
if (pWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, rdr, hdc, HT_MENUBAR);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (fGetDC)
|
|
release_valid_dc (pWin, hdc);
|
|
}
|
|
|
|
/* this function is CONTROL safe. */
|
|
static void wndActiveMainWindow (PMAINWIN pWin, BOOL fActive)
|
|
{
|
|
HDC hdc;
|
|
const WINDOWINFO *wnd_info;
|
|
|
|
hdc = get_valid_dc (pWin, FALSE);
|
|
wnd_info = GetWindowInfo ((HWND)pWin);
|
|
|
|
wnd_info->we_rdr->draw_caption ((HWND)pWin, hdc, fActive);
|
|
if (fActive)
|
|
wnd_info->we_rdr->draw_caption_button ((HWND)pWin, hdc, 0, LFRDR_BTN_STATUS_NORMAL);
|
|
else
|
|
wnd_info->we_rdr->draw_caption_button ((HWND)pWin, hdc, 0, LFRDR_BTN_STATUS_INACTIVE);
|
|
|
|
if (wnd_info->we_rdr->draw_custom_hotspot)
|
|
wnd_info->we_rdr->draw_custom_hotspot ((HWND)pWin, hdc, 0, 0);
|
|
|
|
wnd_info->we_rdr->draw_border ((HWND)pWin, hdc, fActive);
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, wnd_info->we_rdr, hdc, HT_BORDER);
|
|
}
|
|
|
|
release_valid_dc (pWin, hdc);
|
|
}
|
|
|
|
static LRESULT DefaultPaintMsgHandler(PMAINWIN pWin, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch( message ) {
|
|
case MSG_NCPAINT: {
|
|
wndDrawNCFrame (pWin, (HDC)wParam, (const RECT*)lParam);
|
|
break;
|
|
}
|
|
|
|
case MSG_ERASEBKGND:
|
|
if (pWin->WinType == TYPE_CONTROL &&
|
|
pWin->dwExStyle & WS_EX_TRANSPARENT)
|
|
break;
|
|
wndEraseBackground (pWin, (HDC)wParam, (const RECT*)lParam);
|
|
break;
|
|
|
|
case MSG_NCACTIVATE:
|
|
wndActiveMainWindow (pWin, (BOOL)wParam);
|
|
break;
|
|
|
|
case MSG_SYNCPAINT:
|
|
wndActiveMainWindow (pWin, (BOOL)wParam);
|
|
UpdateWindow ((HWND)pWin, TRUE);
|
|
break;
|
|
|
|
case MSG_PAINT: {
|
|
HDC hdc = BeginPaint ((HWND)pWin);
|
|
EndPaint ((HWND)pWin, hdc);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT DefaultControlMsgHandler(PMAINWIN pWin, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HDC hdc;
|
|
int len;
|
|
|
|
switch (message) {
|
|
case MSG_ENABLE:
|
|
if ( (!(pWin->dwStyle & WS_DISABLED) && !wParam)
|
|
|| ((pWin->dwStyle & WS_DISABLED) && wParam) ) {
|
|
if (wParam)
|
|
pWin->dwStyle &= ~WS_DISABLED;
|
|
else
|
|
pWin->dwStyle |= WS_DISABLED;
|
|
}
|
|
break;
|
|
|
|
case MSG_SYSCOMMAND:
|
|
if (wParam == SC_CLOSE)
|
|
SendNotifyMessage ((HWND)pWin, MSG_CLOSE, 0, 0);
|
|
break;
|
|
|
|
case MSG_GETTEXTLENGTH:
|
|
if (pWin->spCaption)
|
|
return strlen (pWin->spCaption);
|
|
else
|
|
return 0;
|
|
|
|
case MSG_GETTEXT:
|
|
if (pWin->spCaption) {
|
|
char* buffer = (char*)lParam;
|
|
|
|
len = MIN (strlen (pWin->spCaption), wParam);
|
|
memcpy (buffer, pWin->spCaption, len);
|
|
buffer [len] = '\0';
|
|
return len;
|
|
}
|
|
else
|
|
return 0;
|
|
break;
|
|
|
|
case MSG_FONTCHANGED:
|
|
UpdateWindow ((HWND)pWin, TRUE);
|
|
break;
|
|
|
|
case MSG_SETTEXT: {
|
|
RECT rc;
|
|
const WINDOWINFO *info;
|
|
/*
|
|
** NOTE:
|
|
** this message is only implemented for main window.
|
|
** for CONTROL, must handle this message and should NOT
|
|
** call default window procedure
|
|
** when handle MSG_SETTEXT.
|
|
*/
|
|
if (pWin->WinType == TYPE_CONTROL)
|
|
return 0;
|
|
|
|
FreeFixStr (pWin->spCaption);
|
|
len = strlen ((char*)lParam);
|
|
pWin->spCaption = FixStrAlloc (len);
|
|
if (len > 0)
|
|
strcpy (pWin->spCaption, (char*)lParam);
|
|
|
|
#ifdef _MGRM_PROCESSES
|
|
SendMessage (HWND_DESKTOP, MSG_CHANGECAPTION, (WPARAM) pWin, 0L);
|
|
#endif
|
|
hdc = get_valid_dc (pWin, FALSE);
|
|
info = GetWindowInfo ((HWND)pWin);
|
|
SetRectEmpty (&rc);
|
|
|
|
if (pWin->dwStyle & WS_MINIMIZEBOX) {
|
|
info->we_rdr->calc_we_area ((HWND)pWin, HT_MINBUTTON, &rc);
|
|
--rc.left;
|
|
--rc.top;
|
|
ExcludeClipRect (hdc, &rc);
|
|
}
|
|
|
|
if (pWin->dwStyle & WS_MAXIMIZEBOX) {
|
|
info->we_rdr->calc_we_area ((HWND)pWin, HT_MAXBUTTON, &rc);
|
|
--rc.left;
|
|
--rc.top;
|
|
ExcludeClipRect (hdc, &rc);
|
|
}
|
|
|
|
if (!(pWin->dwExStyle & WS_EX_NOCLOSEBOX)) {
|
|
info->we_rdr->calc_we_area ((HWND)pWin, HT_CLOSEBUTTON, &rc);
|
|
--rc.left;
|
|
--rc.top;
|
|
ExcludeClipRect (hdc, &rc);
|
|
}
|
|
|
|
/*Draw caption text information*/
|
|
info->we_rdr->draw_caption ((HWND)pWin,
|
|
hdc, GetForegroundWindow () == (HWND)pWin);
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, info->we_rdr, hdc, HT_CAPTION);
|
|
}
|
|
/*It maybe need to delete. */
|
|
#if 0
|
|
if (info->we_rdr->draw_custom_hotspot)
|
|
info->we_rdr->draw_custom_hotspot ((HWND)pWin, hdc, 0, 0);
|
|
#endif
|
|
release_valid_dc (pWin, hdc);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT DefaultSessionMsgHandler(PMAINWIN pWin, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
/*
|
|
** NOTE:
|
|
** Currently does nothing, should handle fowllowing messages:
|
|
**
|
|
** MSG_QUERYENDSESSION:
|
|
** MSG_ENDSESSION:
|
|
*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT DefaultSystemMsgHandler(PMAINWIN pWin, UINT message,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
|
|
/*
|
|
** Should handle following messages:
|
|
**
|
|
** MSG_IDLE, MSG_CARETBLINK:
|
|
*/
|
|
if (message == MSG_IDLE) {
|
|
if (pWin == gui_GetMainWindowPtrOfControl (sg_repeat_msg.hwnd)) {
|
|
SendNotifyMessage (sg_repeat_msg.hwnd,
|
|
sg_repeat_msg.message,
|
|
sg_repeat_msg.wParam, sg_repeat_msg.lParam);
|
|
}
|
|
}
|
|
else if (message == MSG_CARETBLINK && pWin->dwStyle & WS_VISIBLE) {
|
|
BlinkCaret ((HWND)pWin);
|
|
}
|
|
/* houhh 20090619. */
|
|
#ifdef _MGRM_PROCESSES
|
|
else if (message == MSG_UPDATECLIWIN) {
|
|
__mg_update_window ((HWND)pWin,
|
|
LOSWORD(wParam), HISWORD(wParam),
|
|
LOSWORD(lParam), HISWORD(lParam));
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** NOTE:
|
|
** This default main window call-back procedure
|
|
** also implemented for control.
|
|
*/
|
|
LRESULT PreDefMainWinProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hWnd;
|
|
|
|
if (message > MSG_DT_MOUSEOFF && message <= MSG_DT_RBUTTONDBLCLK)
|
|
return DefaultDTMouseMsgHandler(pWin, message,
|
|
wParam, LOSWORD (lParam), HISWORD (lParam));
|
|
else if (message >= MSG_FIRSTMOUSEMSG && message <= MSG_NCMOUSEOFF)
|
|
return DefaultMouseMsgHandler(pWin, message,
|
|
wParam, LOSWORD (lParam), HISWORD (lParam));
|
|
else if (message > MSG_NCMOUSEOFF && message <= MSG_LASTMOUSEMSG)
|
|
return DefaultNCMouseMsgHandler(pWin, message,
|
|
(int)wParam, LOSWORD (lParam), HISWORD (lParam));
|
|
else if (message >= MSG_FIRSTKEYMSG && message <= MSG_LASTKEYMSG)
|
|
return DefaultKeyMsgHandler(pWin, message, wParam, lParam);
|
|
else if (message >= MSG_FIRSTPOSTMSG && message <= MSG_LASTPOSTMSG)
|
|
return DefaultPostMsgHandler(pWin, message, wParam, lParam);
|
|
else if (message >= MSG_FIRSTCREATEMSG && message <= MSG_LASTCREATEMSG)
|
|
return DefaultCreateMsgHandler(pWin, message, wParam, lParam);
|
|
else if (message >= MSG_FIRSTPAINTMSG && message <= MSG_LASTPAINTMSG)
|
|
return DefaultPaintMsgHandler(pWin, message, wParam, lParam);
|
|
else if (message >= MSG_FIRSTSESSIONMSG && message <= MSG_LASTSESSIONMSG)
|
|
return DefaultSessionMsgHandler(pWin, message, wParam, lParam);
|
|
else if (message >= MSG_FIRSTCONTROLMSG && message <= MSG_LASTCONTROLMSG)
|
|
return DefaultControlMsgHandler(pWin, message, wParam, lParam);
|
|
else if (message >= MSG_FIRSTSYSTEMMSG && message <= MSG_LASTSYSTEMMSG)
|
|
return DefaultSystemMsgHandler(pWin, message, wParam, lParam);
|
|
#if (defined(_MG_ENABLE_SCREENSAVER) || defined(_MG_ENABLE_WATERMARK)) && defined(_MGRM_THREADS)
|
|
else if (message == MSG_CANCELSCREENSAVER) {
|
|
__mg_screensaver_hide();
|
|
SendNotifyMessage (HWND_DESKTOP, MSG_PAINT, 0, 0);
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
LRESULT PreDefControlProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (message == MSG_SETTEXT)
|
|
return 0;
|
|
else if (message == MSG_SETCURSOR) {
|
|
if (GetWindowExStyle (hWnd) & WS_EX_USEPARENTCURSOR)
|
|
return 0;
|
|
|
|
SetCursor (GetWindowCursor (hWnd));
|
|
return 0;
|
|
}
|
|
else if (message == MSG_NCSETCURSOR) {
|
|
SetCursor (GetSystemCursor (IDC_ARROW));
|
|
return 0;
|
|
}
|
|
|
|
return DefaultMainWinProc (hWnd, message, wParam, lParam);
|
|
}
|
|
|
|
LRESULT DefaultWindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (IsMainWindow(hWnd)) {
|
|
return DefaultMainWinProc (hWnd, message, wParam, lParam);
|
|
}
|
|
else if (IsControl(hWnd)) {
|
|
return DefaultControlProc (hWnd, message, wParam, lParam);
|
|
}
|
|
else if (IsDialog(hWnd)) {
|
|
return DefaultDialogProc (hWnd, message, wParam, lParam);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/************************* GUI calls support ********************************/
|
|
|
|
static HWND set_focus_helper (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
PMAINWIN old_active;
|
|
|
|
if (IsMainWindow (hWnd))
|
|
return HWND_INVALID;
|
|
|
|
pWin = (PMAINWIN) GetParent (hWnd);
|
|
old_active = (PMAINWIN)pWin->hActiveChild;
|
|
if (old_active != (PMAINWIN)hWnd) {
|
|
|
|
if (old_active)
|
|
SendNotifyMessage ((HWND)old_active, MSG_KILLFOCUS, (WPARAM)hWnd, 1);
|
|
|
|
pWin->hActiveChild = hWnd;
|
|
SendNotifyMessage (hWnd, MSG_SETFOCUS, (WPARAM)old_active, 1);
|
|
}
|
|
|
|
return pWin->hActiveChild;
|
|
}
|
|
|
|
HWND GUIAPI SetFocusChild (HWND hWnd)
|
|
{
|
|
HWND hOldActive;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), HWND_INVALID);
|
|
|
|
if ((hOldActive = set_focus_helper (hWnd)) != HWND_INVALID) {
|
|
do {
|
|
hWnd = GetParent (hWnd);
|
|
} while (set_focus_helper (hWnd) != HWND_INVALID);
|
|
}
|
|
|
|
return hOldActive;
|
|
}
|
|
|
|
HWND GUIAPI GetFocusChild (HWND hParent)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hParent), HWND_INVALID);
|
|
pWin = MG_GET_WINDOW_PTR (hParent);
|
|
return pWin->hActiveChild;
|
|
}
|
|
|
|
HWND GUIAPI SetNullFocus (HWND hParent)
|
|
{
|
|
PMAINWIN pWin;
|
|
HWND hOldActive;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hParent), HWND_INVALID);
|
|
pWin = MG_GET_WINDOW_PTR (hParent);
|
|
|
|
hOldActive = pWin->hActiveChild;
|
|
if (hOldActive)
|
|
SendNotifyMessage (hOldActive, MSG_KILLFOCUS, 0, 0);
|
|
pWin->hActiveChild = 0;
|
|
|
|
return hOldActive;
|
|
}
|
|
|
|
/* NOTE: this function support ONLY main window. */
|
|
HWND GUIAPI SetActiveWindow (HWND hMainWnd)
|
|
{
|
|
if (!MG_IS_NORMAL_WINDOW(hMainWnd) || !IsMainWindow (hMainWnd))
|
|
return HWND_INVALID;
|
|
|
|
return (HWND)SendMessage (HWND_DESKTOP,
|
|
MSG_SETACTIVEMAIN, (WPARAM)hMainWnd, 0);
|
|
}
|
|
|
|
/* NOTE: this function support ONLY main window. */
|
|
HWND GUIAPI GetActiveWindow (void)
|
|
{
|
|
return (HWND)SendMessage (HWND_DESKTOP, MSG_GETACTIVEMAIN, 0, 0);
|
|
}
|
|
|
|
HWND GUIAPI SetCapture (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hWnd;
|
|
|
|
if (hWnd == HWND_INVALID || (pWin && pWin->DataType != TYPE_HWND))
|
|
return HWND_INVALID;
|
|
|
|
/* if hWnd is HWND_DESKTOP or zero, release capture */
|
|
if (hWnd == HWND_DESKTOP) hWnd = 0;
|
|
|
|
return (HWND) SendMessage (HWND_DESKTOP, MSG_SETCAPTURE, (WPARAM)hWnd, 0);
|
|
}
|
|
|
|
|
|
HWND GUIAPI GetCapture (void)
|
|
{
|
|
return (HWND)SendMessage (HWND_DESKTOP, MSG_GETCAPTURE, 0, 0);
|
|
}
|
|
|
|
void GUIAPI ReleaseCapture (void)
|
|
{
|
|
SendMessage (HWND_DESKTOP, MSG_SETCAPTURE, 0, 0);
|
|
}
|
|
|
|
/*************************** Main window and thread **************************/
|
|
|
|
/* get main window pointer from a handle */
|
|
PMAINWIN gui_CheckAndGetMainWindowPtr (HWND hWnd)
|
|
{
|
|
MG_CHECK_RET (MG_IS_NORMAL_MAIN_WINDOW(hWnd), NULL);
|
|
return MG_GET_WINDOW_PTR (hWnd);
|
|
}
|
|
|
|
PMAINWIN gui_GetMainWindowPtrOfControl (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), NULL);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return pWin->pMainWin;
|
|
}
|
|
|
|
BOOL GUIAPI IsWindow (HWND hWnd)
|
|
{
|
|
return MG_IS_NORMAL_WINDOW (hWnd);
|
|
}
|
|
|
|
BOOL GUIAPI IsMainWindow (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
|
|
pWin = MG_GET_WINDOW_PTR(hWnd);
|
|
|
|
return (pWin->WinType == TYPE_MAINWIN);
|
|
}
|
|
|
|
BOOL GUIAPI IsControl (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
|
|
pWin = MG_GET_WINDOW_PTR(hWnd);
|
|
|
|
return (pWin->WinType == TYPE_CONTROL);
|
|
}
|
|
|
|
BOOL GUIAPI IsDialog (HWND hWnd)
|
|
{
|
|
return (BOOL)SendAsyncMessage (hWnd, MSG_ISDIALOG, 0, 0);
|
|
}
|
|
|
|
HWND GUIAPI GetMainWindowHandle (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_WINDOW(hWnd), HWND_INVALID);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return (HWND)pWin->pMainWin;
|
|
}
|
|
|
|
HWND GUIAPI GetParent (HWND hWnd)
|
|
{
|
|
PCONTROL pChildWin = (PCONTROL)hWnd;
|
|
|
|
MG_CHECK_RET (MG_IS_WINDOW(hWnd), HWND_INVALID);
|
|
|
|
return (HWND)pChildWin->pParent;
|
|
}
|
|
|
|
HWND GUIAPI GetHosting (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
if (!(pWin = gui_CheckAndGetMainWindowPtr (hWnd)))
|
|
return HWND_INVALID;
|
|
|
|
if (pWin->pHosting == NULL)
|
|
return HWND_DESKTOP;
|
|
|
|
return (HWND)(pWin->pHosting);
|
|
}
|
|
|
|
HWND GUIAPI GetFirstHosted (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
if (!(pWin = gui_CheckAndGetMainWindowPtr (hWnd)))
|
|
return HWND_INVALID;
|
|
|
|
return (HWND)(pWin->pFirstHosted);
|
|
}
|
|
|
|
HWND GUIAPI GetNextHosted (HWND hHosting, HWND hHosted)
|
|
{
|
|
PMAINWIN pWin;
|
|
PMAINWIN pHosted;
|
|
|
|
if (!(pWin = gui_CheckAndGetMainWindowPtr (hHosting)))
|
|
return HWND_INVALID;
|
|
|
|
if (hHosted == 0) {
|
|
return GetFirstHosted(hHosting);
|
|
}
|
|
|
|
if (!(pHosted = gui_CheckAndGetMainWindowPtr (hHosted)))
|
|
return HWND_INVALID;
|
|
|
|
if (pHosted->pHosting != pWin)
|
|
return HWND_INVALID;
|
|
|
|
return (HWND)(pHosted->pNextHosted);
|
|
}
|
|
|
|
HWND GUIAPI GetNextChild (HWND hWnd, HWND hChild)
|
|
{
|
|
PCONTROL pControl, pChild;
|
|
|
|
if (hChild == HWND_INVALID) return HWND_INVALID;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), HWND_INVALID);
|
|
pControl = MG_GET_CONTROL_PTR(hWnd);
|
|
|
|
pChild = (PCONTROL)hChild;
|
|
|
|
if (pChild == NULL) {
|
|
return (HWND)pControl->children;
|
|
}
|
|
else if (pControl != pChild->pParent) {
|
|
return HWND_INVALID;
|
|
}
|
|
|
|
return (HWND)pChild->next;
|
|
}
|
|
|
|
HWND GUIAPI GetNextMainWindow (HWND hMainWnd)
|
|
{
|
|
PMAINWIN pMainWin;
|
|
|
|
if (hMainWnd == HWND_DESKTOP || hMainWnd == 0)
|
|
pMainWin = NULL;
|
|
else if (!(pMainWin = gui_CheckAndGetMainWindowPtr (hMainWnd)))
|
|
return HWND_INVALID;
|
|
|
|
return (HWND) SendMessage (HWND_DESKTOP,
|
|
MSG_GETNEXTMAINWIN, (WPARAM)pMainWin, 0L);
|
|
}
|
|
|
|
/*
|
|
* TODO: implement ScrollWindowEx completely.
|
|
*/
|
|
int GUIAPI ScrollWindowEx (HWND hWnd, int dx, int dy,
|
|
const RECT *prcScroll, const RECT *prcClip,
|
|
PCLIPRGN pRgnUpdate, PRECT prcUpdate, UINT flags)
|
|
{
|
|
SCROLLWINDOWINFO swi;
|
|
RECT rcClient, rcScroll;
|
|
BOOL fCaret;
|
|
PMAINWIN pWin;
|
|
|
|
if ((dx == 0 && dy == 0))
|
|
return -1;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), -1);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
GetClientRect (hWnd, &rcClient);
|
|
if (prcScroll)
|
|
IntersectRect (&rcScroll, prcScroll, &rcClient);
|
|
else
|
|
rcScroll = rcClient;
|
|
|
|
/*
|
|
* BUGFIX: if we scrolled all area, the all area must
|
|
* be set as invalidate (dongjunjie 2010/7/28)
|
|
*/
|
|
if ((dx != 0 && abs(dx) >= RECTW(rcScroll)) ||
|
|
(dy != 0 && abs(dy) >= RECTH(rcScroll))) {
|
|
InvalidateRect (hWnd, &rcScroll, TRUE);
|
|
goto UPDATERGN;
|
|
}
|
|
|
|
swi.iOffx = dx;
|
|
swi.iOffy = dy;
|
|
swi.rc1 = &rcScroll;
|
|
swi.rc2 = prcClip;
|
|
|
|
/* hide caret */
|
|
fCaret = HideCaretEx (hWnd, FALSE);
|
|
|
|
/* Modify the children's position before scrolling */
|
|
if (flags & SW_SCROLLCHILDREN) {
|
|
PCONTROL child;
|
|
child = ((PCONTROL)hWnd)->children;
|
|
while (child) {
|
|
|
|
if ((prcClip == NULL) ||
|
|
IsCovered ((const RECT*)&child->left, prcClip)) {
|
|
child->left += dx; child->top += dy;
|
|
child->right += dx; child->bottom += dy;
|
|
child->cl += dx; child->ct += dy;
|
|
child->cr += dx; child->cb += dy;
|
|
}
|
|
|
|
child = child->next;
|
|
}
|
|
}
|
|
|
|
SendMessage (HWND_DESKTOP, MSG_SCROLLMAINWIN, (WPARAM)hWnd, (LPARAM)(&swi));
|
|
|
|
/* show caret */
|
|
if (fCaret) ShowCaretEx (hWnd, FALSE);
|
|
|
|
UPDATERGN:
|
|
/* FIXME: we use the invalid region of the window as the update region directly. */
|
|
if (pRgnUpdate) {
|
|
/* copy from window's invalidate region */
|
|
RECT rcClient;
|
|
RECT rc;
|
|
CopyRegion (pRgnUpdate, &pWin->InvRgn.rgn);
|
|
/* FIXME: I have not the best idea to do this */
|
|
GetClientRect (hWnd, &rcClient);
|
|
rc = rcClient;
|
|
if (dx > 0)
|
|
rc.right = rc.left + dx + 1;
|
|
else if (dx < 0)
|
|
rc.left = rc.right + dx - 1;
|
|
if (dx != 0)
|
|
AddClipRect (pRgnUpdate, &rc);
|
|
rc = rcClient;
|
|
if (dy > 0)
|
|
rc.bottom = rc.top + dy + 1;
|
|
else if (dy < 0)
|
|
rc.top = rc.bottom + dy - 1;
|
|
if (dy != 0)
|
|
AddClipRect (pRgnUpdate, &rc);
|
|
}
|
|
|
|
if (prcUpdate) {
|
|
if (pRgnUpdate)
|
|
*prcUpdate = pRgnUpdate->rcBound;
|
|
else if (dx != 0 && dy != 0)
|
|
GetClientRect (hWnd, prcUpdate);
|
|
else if (dx != 0) {
|
|
GetClientRect (hWnd, prcUpdate);
|
|
if (dx > 0)
|
|
prcUpdate->right = prcUpdate->left + dx + 1;
|
|
else
|
|
prcUpdate->left = prcUpdate->right + dx - 1;
|
|
}
|
|
else if (dy != 0) {
|
|
GetClientRect (hWnd, prcUpdate);
|
|
if (dy > 0)
|
|
prcUpdate->bottom = prcUpdate->top + dx + 1;
|
|
else
|
|
prcUpdate->top = prcUpdate->bottom + dx - 1;
|
|
}
|
|
else
|
|
*prcUpdate = pWin->InvRgn.rgn.rcBound;
|
|
}
|
|
|
|
return pWin->InvRgn.rgn.type;
|
|
}
|
|
|
|
static PLFSCROLLBARINFO wndGetScrollBar (MAINWIN* pWin, int iSBar)
|
|
{
|
|
if (iSBar == SB_HORZ) {
|
|
if (pWin->dwStyle & WS_HSCROLL)
|
|
return &pWin->hscroll;
|
|
}
|
|
else if (iSBar == SB_VERT) {
|
|
if (pWin->dwStyle & WS_VSCROLL)
|
|
return &pWin->vscroll;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
BOOL GUIAPI EnableScrollBar (HWND hWnd, int iSBar, BOOL bEnable)
|
|
{
|
|
PLFSCROLLBARINFO pSBar;
|
|
PMAINWIN pWin;
|
|
BOOL bPrevState;
|
|
RECT rcBar;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )
|
|
return FALSE;
|
|
|
|
bPrevState = !(pSBar->status & SBS_DISABLED);
|
|
|
|
if (bEnable && !bPrevState)
|
|
pSBar->status &= ~SBS_DISABLED;
|
|
else if (!bEnable && bPrevState)
|
|
pSBar->status |= SBS_DISABLED;
|
|
else
|
|
return FALSE;
|
|
|
|
if (iSBar == SB_VERT)
|
|
wndGetVScrollBarRect (pWin, &rcBar);
|
|
else
|
|
wndGetHScrollBarRect (pWin, &rcBar);
|
|
|
|
SendAsyncMessage (hWnd, MSG_NCPAINT, 0, (LPARAM)(&rcBar));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI GetScrollPos (HWND hWnd, int iSBar, int* pPos)
|
|
{
|
|
PLFSCROLLBARINFO pSBar;
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )
|
|
return FALSE;
|
|
|
|
*pPos = pSBar->curPos;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI GetScrollRange (HWND hWnd, int iSBar, int* pMinPos, int* pMaxPos)
|
|
{
|
|
PLFSCROLLBARINFO pSBar;
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )
|
|
return FALSE;
|
|
|
|
*pMinPos = pSBar->minPos;
|
|
*pMaxPos = pSBar->maxPos;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI SetScrollPos (HWND hWnd, int iSBar, int iNewPos)
|
|
{
|
|
PLFSCROLLBARINFO pSBar;
|
|
PMAINWIN pWin;
|
|
//const WINDOWINFO *info = GetWindowInfo (hWnd);
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )
|
|
return FALSE;
|
|
|
|
if (iNewPos == pSBar->curPos)
|
|
return TRUE;
|
|
|
|
if (iNewPos < pSBar->minPos)
|
|
pSBar->curPos = pSBar->minPos;
|
|
else
|
|
pSBar->curPos = iNewPos;
|
|
|
|
{
|
|
int max = pSBar->maxPos;
|
|
max -= ((pSBar->pageStep - 1) > 0)?(pSBar->pageStep - 1):0;
|
|
|
|
if (pSBar->curPos > max)
|
|
pSBar->curPos = max;
|
|
}
|
|
|
|
RecalcScrollInfo (pWin, iSBar == SB_HORZ);
|
|
|
|
if(iSBar == SB_VERT)
|
|
{
|
|
// if (!(pWin->vscroll.status & SBS_HIDE ||
|
|
// pWin->vscroll.status & SBS_DISABLED))
|
|
wndDrawNCButton (pWin, HT_VSCROLL, 0);
|
|
}
|
|
else
|
|
{
|
|
// if (!(pWin->hscroll.status & SBS_HIDE ||
|
|
// pWin->hscroll.status & SBS_DISABLED))
|
|
wndDrawNCButton (pWin, HT_HSCROLL, 0);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI SetScrollRange (HWND hWnd, int iSBar, int iMinPos, int iMaxPos)
|
|
{
|
|
PLFSCROLLBARINFO pSBar;
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )
|
|
return FALSE;
|
|
|
|
if (iMinPos == pSBar->minPos && iMaxPos == pSBar->maxPos)
|
|
return TRUE;
|
|
|
|
pSBar->minPos = (iMinPos < iMaxPos)?iMinPos:iMaxPos;
|
|
pSBar->maxPos = (iMinPos > iMaxPos)?iMinPos:iMaxPos;
|
|
|
|
/* validate parameters. */
|
|
if (pSBar->curPos < pSBar->minPos)
|
|
pSBar->curPos = pSBar->minPos;
|
|
|
|
if (pSBar->pageStep <= 0)
|
|
pSBar->pageStep = 0;
|
|
else if (pSBar->pageStep > (pSBar->maxPos - pSBar->minPos + 1))
|
|
pSBar->pageStep = pSBar->maxPos - pSBar->minPos + 1;
|
|
|
|
{
|
|
int max = pSBar->maxPos;
|
|
max -= ((pSBar->pageStep - 1) > 0)?(pSBar->pageStep - 1):0;
|
|
|
|
if (pSBar->curPos > max)
|
|
pSBar->curPos = max;
|
|
}
|
|
|
|
RecalcScrollInfo (pWin, iSBar == SB_HORZ);
|
|
|
|
if(iSBar == SB_VERT)
|
|
{
|
|
// if (!(pWin->vscroll.status & SBS_HIDE ||
|
|
// pWin->vscroll.status & SBS_DISABLED))
|
|
wndDrawNCButton (pWin, HT_VSCROLL, 0);
|
|
}
|
|
else
|
|
{
|
|
// if (!(pWin->hscroll.status & SBS_HIDE ||
|
|
// pWin->hscroll.status & SBS_DISABLED))
|
|
wndDrawNCButton (pWin, HT_HSCROLL, 0);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
int wndScrollBarSliderStartPos (MAINWIN *pWin, int iSBar)
|
|
{
|
|
int start = 0;
|
|
int sb = GetWindowElementAttr ((HWND)pWin, WE_METRICS_SCROLLBAR);
|
|
|
|
if (iSBar == SB_HORZ) {
|
|
RECT rcHBar;
|
|
|
|
wndGetHScrollBarRect (pWin, &rcHBar);
|
|
start = rcHBar.left +
|
|
pWin->hscroll.barStart + sb;
|
|
}
|
|
else if (iSBar == SB_VERT) {
|
|
RECT rcVBar;
|
|
|
|
wndGetVScrollBarRect (pWin, &rcVBar);
|
|
start = rcVBar.top +
|
|
pWin->vscroll.barStart + sb;
|
|
|
|
if (start + pWin->vscroll.barLen > rcVBar.bottom)
|
|
start = rcVBar.bottom - pWin->vscroll.barLen;
|
|
}
|
|
|
|
return start;
|
|
}
|
|
|
|
BOOL GUIAPI SetScrollInfo (HWND hWnd, int iSBar,
|
|
const SCROLLINFO* lpsi, BOOL fRedraw)
|
|
{
|
|
PLFSCROLLBARINFO pSBar;
|
|
PMAINWIN pWin;
|
|
RECT rcBar;
|
|
DWORD changed_mask = 0;
|
|
int sb;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )
|
|
return FALSE;
|
|
|
|
if (lpsi->fMask & SIF_RANGE) {
|
|
if (pSBar->minPos != lpsi->nMin || pSBar->maxPos != lpsi->nMax) {
|
|
changed_mask |= SIF_RANGE;
|
|
}
|
|
}
|
|
|
|
if (lpsi->fMask & SIF_POS && pSBar->curPos != lpsi->nPos) {
|
|
changed_mask |= SIF_POS;
|
|
}
|
|
|
|
if (lpsi->fMask & SIF_PAGE && pSBar->pageStep != lpsi->nPage) {
|
|
changed_mask |= SIF_PAGE;
|
|
}
|
|
|
|
if (changed_mask == 0)
|
|
return TRUE;
|
|
else if (changed_mask == SIF_POS)
|
|
return SetScrollPos (hWnd, iSBar, lpsi->nPos);
|
|
|
|
if (changed_mask & SIF_RANGE) {
|
|
pSBar->minPos = (lpsi->nMin < lpsi->nMax)?lpsi->nMin:lpsi->nMax;
|
|
pSBar->maxPos = (lpsi->nMin < lpsi->nMax)?lpsi->nMax:lpsi->nMin;
|
|
}
|
|
|
|
if (changed_mask & SIF_POS)
|
|
pSBar->curPos = lpsi->nPos;
|
|
|
|
if (changed_mask & SIF_PAGE)
|
|
pSBar->pageStep = lpsi->nPage;
|
|
|
|
/* validate parameters. */
|
|
if (pSBar->curPos < pSBar->minPos)
|
|
pSBar->curPos = pSBar->minPos;
|
|
|
|
if (pSBar->pageStep <= 0)
|
|
pSBar->pageStep = 0;
|
|
else if (pSBar->pageStep > (pSBar->maxPos - pSBar->minPos + 1))
|
|
pSBar->pageStep = pSBar->maxPos - pSBar->minPos + 1;
|
|
|
|
{
|
|
int max = pSBar->maxPos;
|
|
max -= ((pSBar->pageStep - 1) > 0)?(pSBar->pageStep - 1):0;
|
|
|
|
if (pSBar->curPos > max)
|
|
pSBar->curPos = max;
|
|
}
|
|
|
|
if (fRedraw) {
|
|
HDC hdc;
|
|
|
|
if (iSBar == SB_VERT)
|
|
wndGetVScrollBarRect (pWin, &rcBar);
|
|
else
|
|
wndGetHScrollBarRect (pWin, &rcBar);
|
|
|
|
RecalcScrollInfo (pWin, iSBar == SB_HORZ);
|
|
|
|
sb = GetWindowElementAttr ((HWND)pWin, WE_METRICS_SCROLLBAR);
|
|
if (iSBar == SB_VERT) {
|
|
rcBar.top += sb;
|
|
rcBar.bottom -= sb;
|
|
}
|
|
else {
|
|
rcBar.left += sb;
|
|
rcBar.right -= sb;
|
|
}
|
|
|
|
hdc = GetDC (hWnd);
|
|
ClipRectIntersect (hdc, &rcBar);
|
|
|
|
if(iSBar == SB_VERT)
|
|
{
|
|
// if (!(pWin->vscroll.status & SBS_HIDE ||
|
|
// pWin->vscroll.status & SBS_DISABLED))
|
|
wndDrawNCButton (pWin, HT_VSCROLL, 0);
|
|
}
|
|
else
|
|
{
|
|
// if (!(pWin->hscroll.status & SBS_HIDE ||
|
|
// pWin->hscroll.status & SBS_DISABLED))
|
|
wndDrawNCButton (pWin, HT_HSCROLL, 0);
|
|
}
|
|
|
|
ReleaseDC (hdc);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI GetScrollInfo (HWND hWnd, int iSBar, PSCROLLINFO lpsi)
|
|
{
|
|
PLFSCROLLBARINFO pSBar;
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if (!(pSBar = wndGetScrollBar (pWin, iSBar)))
|
|
return FALSE;
|
|
|
|
if (lpsi->fMask & SIF_RANGE) {
|
|
lpsi->nMin = pSBar->minPos;
|
|
lpsi->nMax = pSBar->maxPos;
|
|
}
|
|
|
|
if (lpsi->fMask & SIF_POS) {
|
|
lpsi->nPos = pSBar->curPos;
|
|
}
|
|
|
|
if (lpsi->fMask & SIF_PAGE)
|
|
lpsi->nPage = pSBar->pageStep;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI ShowScrollBar (HWND hWnd, int iSBar, BOOL bShow)
|
|
{
|
|
//
|
|
PLFSCROLLBARINFO pSBar;
|
|
PMAINWIN pWin;
|
|
BOOL bPrevState;
|
|
RECT rcBar;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if ( !(pSBar = wndGetScrollBar (pWin, iSBar)) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
bPrevState = !(pSBar->status & SBS_HIDE);
|
|
|
|
if( (bPrevState && bShow) || (!bPrevState && !bShow))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//TO AVOID THE DEAD LOOP
|
|
if (!bPrevState
|
|
&& ((pSBar->minPos == pSBar->maxPos)
|
|
|| (pSBar->pageStep >= (pSBar->maxPos - pSBar->minPos))))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (iSBar == SB_VERT)
|
|
wndGetVScrollBarRect (pWin, &rcBar);
|
|
else
|
|
wndGetHScrollBarRect (pWin, &rcBar);
|
|
|
|
//HEAR, status Changed,
|
|
if(bShow)
|
|
pSBar->status &= ~SBS_HIDE;
|
|
else
|
|
pSBar->status |= SBS_HIDE;
|
|
|
|
//Hear , MSG_CHANGESIZE would call OnChangeSize
|
|
//OnChangeSize May be modify pSBar->status as 100
|
|
//( pSBar->status|=SBS_HIDE), when
|
|
// pSBar's pageStep >= max -min
|
|
// And Then, RecalcClientArea would be called,
|
|
// RecalcClientArea will send MSG_CHANGESIZE,
|
|
// In some controls, it will process MSG_CHANGESIZE
|
|
// and call ShowScrollBar too.
|
|
// Becareful the MSG_CHANGESIZE !!!
|
|
SendAsyncMessage (hWnd, MSG_CHANGESIZE, 0, 0);
|
|
|
|
/* houhh 20081006, pSbar->status |= SBS_HIDE, Get rcBar is error.
|
|
*/
|
|
#if 0
|
|
if (iSBar == SB_VERT)
|
|
wndGetVScrollBarRect (pWin, &rcBar);
|
|
else
|
|
wndGetHScrollBarRect (pWin, &rcBar);
|
|
#endif
|
|
|
|
InflateRect (&rcBar, 1, 1);
|
|
|
|
if (bShow) {
|
|
SendAsyncMessage (hWnd, MSG_NCPAINT, 0, 0);
|
|
}
|
|
else {
|
|
/* tranlate the rcBar coordinate relative to client area. */
|
|
RECT cli_rc;
|
|
const WINDOWINFO *info = GetWindowInfo (hWnd);
|
|
info->we_rdr->calc_we_area (hWnd, HT_CLIENT, &cli_rc);
|
|
SendAsyncMessage (hWnd, MSG_NCPAINT, 0, 0);
|
|
rcBar.left -= cli_rc.left;
|
|
rcBar.top -= cli_rc.top;
|
|
rcBar.right -= cli_rc.left;
|
|
rcBar.bottom -= cli_rc.top;
|
|
InvalidateRect (hWnd, &rcBar, TRUE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************** Main window creation ****************************/
|
|
#ifdef _MGRM_THREADS
|
|
int GUIAPI CreateThreadForMainWindow (pthread_t* thread,
|
|
pthread_attr_t* attr,
|
|
void * (*start_routine)(void *),
|
|
void * arg)
|
|
{
|
|
pthread_attr_t new_attr;
|
|
int ret;
|
|
|
|
pthread_attr_init (&new_attr);
|
|
if (attr == NULL) {
|
|
attr = &new_attr;
|
|
pthread_attr_setdetachstate (attr, PTHREAD_CREATE_DETACHED);
|
|
#ifdef __NOUNIX__
|
|
/* hope 16KB is enough for MiniGUI */
|
|
pthread_attr_setstacksize (attr, 16 * 1024);
|
|
#endif
|
|
}
|
|
|
|
ret = pthread_create(thread, attr, start_routine, arg);
|
|
|
|
pthread_attr_destroy (&new_attr);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int GUIAPI WaitMainWindowClose (HWND hWnd, void** returnval)
|
|
{
|
|
pthread_t th;
|
|
|
|
if (!(gui_CheckAndGetMainWindowPtr(hWnd)))
|
|
return -1;
|
|
|
|
th = GetMainWinThread (hWnd);
|
|
|
|
return pthread_join (th, returnval);
|
|
}
|
|
#endif
|
|
|
|
void GUIAPI MainWindowThreadCleanup (HWND hMainWnd)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hMainWnd;
|
|
|
|
_DBG_PRINTF ("window(%p), caption(%s)\n", pWin, pWin->spCaption);
|
|
|
|
if (!MG_IS_DESTROYED_WINDOW (hMainWnd)) {
|
|
_WRN_PRINTF ("Unexpected calling(%s); Window(%p) not destroyed yet!\n",
|
|
__FUNCTION__, hMainWnd);
|
|
return;
|
|
}
|
|
|
|
#ifdef _MGRM_THREADS
|
|
if (pWin->pHosting == NULL) {
|
|
mg_FreeMsgQueueThisThread ();
|
|
_DBG_PRINTF ("Message queure is freed: %p (%s)\n", pWin, pWin->spCaption);
|
|
}
|
|
#endif
|
|
|
|
#ifdef __THREADX__
|
|
/* to avoid threadx keep pWin's value,which will lead to wrong way */
|
|
memset (pWin, 0xcc, sizeof(MAINWIN));
|
|
#endif
|
|
|
|
free (pWin);
|
|
}
|
|
|
|
#ifdef __TARGET_FMSOFT__
|
|
/* To handle main window offset */
|
|
int __mg_mainwin_offset_x;
|
|
int __mg_mainwin_offset_y;
|
|
#endif
|
|
|
|
static void set_window_renderer (PMAINWIN pWin, const char* werdr_name)
|
|
{
|
|
const WINDOW_ELEMENT_RENDERER* renderer =
|
|
GetWindowRendererFromName (werdr_name);
|
|
|
|
if (renderer)
|
|
pWin->we_rdr = (WINDOW_ELEMENT_RENDERER*)renderer;
|
|
else
|
|
pWin->we_rdr = __mg_def_renderer;
|
|
|
|
if (pWin->we_rdr)
|
|
++pWin->we_rdr->refcount;
|
|
}
|
|
|
|
/*
|
|
* ResetMenuSize:
|
|
* reset menu height
|
|
*
|
|
* Author : NuohuaZhou
|
|
* Data : 2007-11-22
|
|
*/
|
|
static void ResetMenuSize (HWND hwnd)
|
|
{
|
|
/** font size of renderer */
|
|
int font_size;
|
|
|
|
/** min menu size of renderer */
|
|
int menu_height_min;
|
|
|
|
/** expect menu size of renderer */
|
|
int menu_height_expect;
|
|
|
|
font_size = ((PLOGFONT)GetWindowElementAttr (hwnd, WE_FONT_MENU))->size;
|
|
menu_height_min = font_size + (LFRDR_MENUITEMOFFY_MIN << 1);
|
|
menu_height_expect = GetWindowElementAttr (hwnd, WE_METRICS_MENU);
|
|
|
|
/** reset menu height */
|
|
if (menu_height_expect < menu_height_min) {
|
|
SetWindowElementAttr (hwnd, WE_METRICS_MENU, menu_height_min);
|
|
}
|
|
}
|
|
|
|
HWND GUIAPI CreateMainWindowEx2 (PMAINWINCREATE pCreateInfo,
|
|
const char* werdr_name, const WINDOW_ELEMENT_ATTR* we_attrs,
|
|
unsigned int surf_flag, int ct, DWORD ct_arg,
|
|
const char* window_name, const char* layer_name)
|
|
{
|
|
PMAINWIN pWin;
|
|
COMPOSITINGINFO ct_info = { ct, ct_arg };
|
|
|
|
if (pCreateInfo == NULL) {
|
|
return HWND_INVALID;
|
|
}
|
|
|
|
if (!(pWin = calloc (1, sizeof(MAINWIN)))) {
|
|
return HWND_INVALID;
|
|
}
|
|
|
|
#ifdef _MGRM_THREADS
|
|
if (pCreateInfo->hHosting == HWND_DESKTOP || pCreateInfo->hHosting == 0) {
|
|
/*
|
|
** Create thread infomation and message queue for this new main window.
|
|
*/
|
|
if ((pWin->pMessages = GetMsgQueueThisThread ()) == NULL) {
|
|
if (!(pWin->pMessages = mg_InitMsgQueueThisThread ()) ) {
|
|
free (pWin);
|
|
|
|
return HWND_INVALID;
|
|
}
|
|
pWin->pMessages->pRootMainWin = pWin;
|
|
}
|
|
else {
|
|
/* Already have a top level main window, in case of user have set
|
|
a wrong hosting window */
|
|
pWin->pHosting = pWin->pMessages->pRootMainWin;
|
|
}
|
|
}
|
|
else {
|
|
pWin->pMessages = GetMsgQueueThisThread ();
|
|
if (pWin->pMessages != kernel_GetMsgQueue (pCreateInfo->hHosting) ||
|
|
pWin->pMessages == NULL) {
|
|
free (pWin);
|
|
|
|
return HWND_INVALID;
|
|
}
|
|
}
|
|
|
|
if (pWin->pHosting == NULL)
|
|
pWin->pHosting = gui_GetMainWindowPtrOfControl (pCreateInfo->hHosting);
|
|
/* leave the pHosting is NULL for the first window of this thread. */
|
|
#else
|
|
pWin->pHosting = gui_GetMainWindowPtrOfControl (pCreateInfo->hHosting);
|
|
if (pWin->pHosting == NULL)
|
|
pWin->pHosting = __mg_dsk_win;
|
|
|
|
pWin->pMessages = __mg_dsk_msg_queue;
|
|
#endif
|
|
|
|
pWin->pMainWin = pWin;
|
|
pWin->hParent = 0;
|
|
pWin->pFirstHosted = NULL;
|
|
pWin->pNextHosted = NULL;
|
|
pWin->DataType = TYPE_HWND;
|
|
pWin->WinType = TYPE_MAINWIN;
|
|
|
|
#ifdef _MGRM_THREADS
|
|
pWin->th = pthread_self();
|
|
#endif
|
|
|
|
pWin->hFirstChild = 0;
|
|
pWin->hActiveChild = 0;
|
|
pWin->hOldUnderPointer = 0;
|
|
pWin->hPrimitive = 0;
|
|
|
|
pWin->NotifProc = NULL;
|
|
|
|
pWin->dwStyle = pCreateInfo->dwStyle;
|
|
pWin->dwExStyle = pCreateInfo->dwExStyle;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
pWin->hMenu = pCreateInfo->hMenu;
|
|
#else
|
|
pWin->hMenu = 0;
|
|
#endif
|
|
pWin->hCursor = pCreateInfo->hCursor;
|
|
pWin->hIcon = pCreateInfo->hIcon;
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if ((pWin->dwStyle & WS_CAPTION) && (pWin->dwStyle & WS_SYSMENU))
|
|
pWin->hSysMenu= CreateSystemMenu ((HWND)pWin, pWin->dwStyle);
|
|
else
|
|
#endif
|
|
pWin->hSysMenu = 0;
|
|
|
|
pWin->spCaption = FixStrAlloc (strlen (pCreateInfo->spCaption));
|
|
if (pCreateInfo->spCaption [0])
|
|
strcpy (pWin->spCaption, pCreateInfo->spCaption);
|
|
|
|
pWin->MainWindowProc = pCreateInfo->MainWindowProc;
|
|
pWin->iBkColor = pCreateInfo->iBkColor;
|
|
|
|
pWin->pCaretInfo = NULL;
|
|
|
|
pWin->dwAddData = pCreateInfo->dwAddData;
|
|
pWin->dwAddData2 = 0;
|
|
pWin->secondaryDC = 0;
|
|
|
|
/* Scroll bar */
|
|
if (pWin->dwStyle & WS_VSCROLL) {
|
|
pWin->vscroll.minPos = 0;
|
|
pWin->vscroll.maxPos = 100;
|
|
pWin->vscroll.curPos = 0;
|
|
pWin->vscroll.pageStep = 101;
|
|
pWin->vscroll.barStart = 0;
|
|
pWin->vscroll.barLen = 10;
|
|
pWin->vscroll.status = SBS_NORMAL;
|
|
}
|
|
else
|
|
pWin->vscroll.status = SBS_HIDE | SBS_DISABLED;
|
|
|
|
if (pWin->dwStyle & WS_HSCROLL) {
|
|
pWin->hscroll.minPos = 0;
|
|
pWin->hscroll.maxPos = 100;
|
|
pWin->hscroll.curPos = 0;
|
|
pWin->hscroll.pageStep = 101;
|
|
pWin->hscroll.barStart = 0;
|
|
pWin->hscroll.barLen = 10;
|
|
pWin->hscroll.status = SBS_NORMAL;
|
|
}
|
|
else
|
|
pWin->hscroll.status = SBS_HIDE | SBS_DISABLED;
|
|
|
|
/** perfer to use parent renderer */
|
|
if (pWin->dwExStyle & WS_EX_USEPARENTRDR) {
|
|
if (((PMAINWIN)pCreateInfo->hHosting)->we_rdr) {
|
|
pWin->we_rdr = ((PMAINWIN)pCreateInfo->hHosting)->we_rdr;
|
|
++pWin->we_rdr->refcount;
|
|
}
|
|
else {
|
|
return HWND_INVALID;
|
|
}
|
|
}
|
|
else {
|
|
/** set window renderer */
|
|
set_window_renderer (pWin, werdr_name);
|
|
}
|
|
|
|
/** set window element data */
|
|
while (we_attrs && we_attrs->we_attr_id != -1) {
|
|
// __mg_append_window_element_data (pWin,
|
|
// we_attrs->we_attr_id, we_attrs->we_attr);
|
|
DWORD _old;
|
|
__mg_set_window_element_data ((HWND)pWin,
|
|
we_attrs->we_attr_id, we_attrs->we_attr, &_old);
|
|
++we_attrs;
|
|
}
|
|
|
|
/** prefer to parent font */
|
|
if (pWin->dwExStyle & WS_EX_USEPARENTFONT)
|
|
pWin->pLogFont = __mg_dsk_win->pLogFont;
|
|
else {
|
|
pWin->pLogFont = GetSystemFont (SYSLOGFONT_WCHAR_DEF);
|
|
}
|
|
|
|
if (SendMessage ((HWND)pWin, MSG_NCCREATE, 0, (LPARAM)pCreateInfo))
|
|
goto err;
|
|
|
|
/** reset menu size */
|
|
ResetMenuSize ((HWND)pWin);
|
|
|
|
#ifdef __TARGET_FMSOFT__
|
|
pCreateInfo->lx += __mg_mainwin_offset_x;
|
|
pCreateInfo->rx += __mg_mainwin_offset_x;
|
|
pCreateInfo->ty += __mg_mainwin_offset_y;
|
|
pCreateInfo->by += __mg_mainwin_offset_y;
|
|
#endif
|
|
|
|
SendMessage ((HWND)pWin, MSG_SIZECHANGING,
|
|
(WPARAM)&pCreateInfo->lx, (LPARAM)&pWin->left);
|
|
SendMessage ((HWND)pWin, MSG_CHANGESIZE, (WPARAM)&pWin->left, 0);
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
pWin->surf = GAL_CreateSurfaceForZNode (surf_flag, pWin->right - pWin->left,
|
|
pWin->bottom - pWin->top);
|
|
if ((surf_flag & ST_PIXEL_MASK) != ST_PIXEL_DEFAULT) {
|
|
pWin->iBkColor = GAL_MapRGBA (pWin->surf->format,
|
|
GetRValue (pCreateInfo->dwBkColor), GetGValue (pCreateInfo->dwBkColor),
|
|
GetBValue (pCreateInfo->dwBkColor), GetAValue (pCreateInfo->dwBkColor));
|
|
}
|
|
#else
|
|
pWin->pGCRInfo = &pWin->GCRInfo;
|
|
#endif
|
|
|
|
if (SendMessage (HWND_DESKTOP, MSG_ADDNEWMAINWIN,
|
|
(WPARAM)pWin, (LPARAM)&ct_info) < 0)
|
|
goto err;
|
|
|
|
/* houhh20081127, Move these code into dskAddNewMainWindow().*/
|
|
#if 0
|
|
/* Create secondary window dc. */
|
|
if (pWin->dwExStyle & WS_EX_AUTOSECONDARYDC)
|
|
pWin->secondaryDC = CreateSecondaryDC ((HWND)pWin);
|
|
#endif
|
|
|
|
/*
|
|
* We should add the new main window in system and then
|
|
* SendMessage MSG_CREATE for application to create
|
|
* child windows.
|
|
*/
|
|
if (SendMessage ((HWND)pWin, MSG_CREATE, 0, (LPARAM)pCreateInfo)) {
|
|
SendMessage(HWND_DESKTOP, MSG_REMOVEMAINWIN, (WPARAM)pWin, 0);
|
|
goto err;
|
|
}
|
|
|
|
#if 0
|
|
/* Create private client dc. */
|
|
if (pWin->dwExStyle & WS_EX_USEPRIVATECDC) {
|
|
if (pWin->dwExStyle & WS_EX_AUTOSECONDARYDC)
|
|
pWin->privCDC = GetSecondarySubDC (pWin->secondaryDC, (HWND)pWin, TRUE);
|
|
else
|
|
pWin->privCDC = CreatePrivateClientDC ((HWND)pWin);
|
|
}
|
|
else
|
|
pWin->privCDC = 0;
|
|
#endif
|
|
|
|
#ifndef _MGRM_PROCESSES
|
|
__mg_screensaver_create();
|
|
#endif
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
// Close file descriptor to free kernel memory?
|
|
if (pWin->surf->shared_header) {
|
|
close (pWin->surf->shared_header->fd);
|
|
pWin->surf->shared_header->fd = -1;
|
|
}
|
|
#endif
|
|
|
|
/* Since 4.2.0: exclude the special window type style if failed */
|
|
if ((pWin->dwExStyle & WS_EX_WINTYPE_MASK) == WS_EX_WINTYPE_SCREENLOCK &&
|
|
pWin->idx_znode != ZNIDX_SCREENLOCK) {
|
|
pWin->dwExStyle &= ~WS_EX_WINTYPE_MASK;
|
|
}
|
|
else if ((pWin->dwExStyle & WS_EX_WINTYPE_MASK) == WS_EX_WINTYPE_DOCKER &&
|
|
pWin->idx_znode != ZNIDX_DOCKER) {
|
|
pWin->dwExStyle &= ~WS_EX_WINTYPE_MASK;
|
|
}
|
|
else if ((pWin->dwExStyle & WS_EX_WINTYPE_MASK) == WS_EX_WINTYPE_LAUNCHER &&
|
|
pWin->idx_znode != ZNIDX_LAUNCHER) {
|
|
pWin->dwExStyle &= ~WS_EX_WINTYPE_MASK;
|
|
}
|
|
|
|
return (HWND)pWin;
|
|
|
|
err:
|
|
#ifdef _MGRM_THREADS
|
|
if (pWin->pMessages && pWin->pHosting == NULL) {
|
|
mg_FreeMsgQueueThisThread ();
|
|
}
|
|
#endif
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
if (pWin->surf)
|
|
GAL_FreeSurface (pWin->surf);
|
|
#endif
|
|
if (pWin->secondaryDC)
|
|
DeleteSecondaryDC ((HWND)pWin);
|
|
|
|
free (pWin);
|
|
return HWND_INVALID;
|
|
}
|
|
|
|
BOOL GUIAPI DestroyMainWindow (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
PMAINWIN head, next; /* hosted window list. */
|
|
|
|
if (!(pWin = gui_CheckAndGetMainWindowPtr (hWnd))) return FALSE;
|
|
|
|
if (SendMessage (hWnd, MSG_DESTROY, 0, 0))
|
|
return FALSE;
|
|
|
|
/* destroy all controls of this window */
|
|
DestroyAllControls (hWnd);
|
|
|
|
/* destroy all hosted main windows and dialogs here. */
|
|
head = pWin->pFirstHosted;
|
|
while (head) {
|
|
next = head->pNextHosted;
|
|
|
|
if (IsDialog((HWND)head)) {
|
|
EndDialog ((HWND)head, IDCANCEL);
|
|
}
|
|
else {
|
|
if (DestroyMainWindow ((HWND)head))
|
|
MainWindowCleanup ((HWND)head);
|
|
}
|
|
|
|
head = next;
|
|
}
|
|
|
|
/* kill all timers of this window */
|
|
KillTimer (hWnd, 0);
|
|
|
|
SendMessage(HWND_DESKTOP, MSG_REMOVEMAINWIN, (WPARAM)hWnd, 0);
|
|
|
|
if (sg_repeat_msg.hwnd == hWnd)
|
|
sg_repeat_msg.hwnd = 0;
|
|
|
|
/* make the window to be invalid for PeekMessageEx, PostMessage etc */
|
|
pWin->DataType = TYPE_WINTODEL;
|
|
|
|
ThrowAwayMessages (hWnd);
|
|
|
|
/* houhh 20081127, move these code to .*/
|
|
#if 0
|
|
if ((pWin->dwExStyle & WS_EX_AUTOSECONDARYDC) && pWin->secondaryDC) {
|
|
DeleteSecondaryDC (hWnd);
|
|
pWin->update_secdc = NULL;
|
|
}
|
|
|
|
if (pWin->privCDC) {
|
|
if (pWin->dwExStyle & WS_EX_AUTOSECONDARYDC) {
|
|
ReleaseSecondarySubDC (pWin->privCDC);
|
|
}
|
|
else
|
|
DeletePrivateDC (pWin->privCDC);
|
|
pWin->privCDC = 0;
|
|
}
|
|
#endif
|
|
|
|
if (pWin->spCaption) {
|
|
FreeFixStr (pWin->spCaption);
|
|
pWin->spCaption = NULL;
|
|
}
|
|
|
|
#ifdef _MGHAVE_MENU
|
|
if (pWin->hMenu) {
|
|
DestroyMenu (pWin->hMenu);
|
|
pWin->hMenu = 0;
|
|
}
|
|
|
|
if (pWin->hSysMenu) {
|
|
DestroyMenu (pWin->hSysMenu);
|
|
pWin->hSysMenu = 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
GAL_FreeSurface (pWin->surf);
|
|
#else
|
|
EmptyClipRgn (&pWin->pGCRInfo->crgn);
|
|
#endif
|
|
EmptyClipRgn (&pWin->InvRgn.rgn);
|
|
|
|
__mg_free_window_element_data (hWnd);
|
|
--pWin->we_rdr->refcount;
|
|
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_destroy (&pWin->pGCRInfo->lock);
|
|
pthread_mutex_destroy (&pWin->InvRgn.lock);
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************** Main window creation ****************************/
|
|
void GUIAPI UpdateWindow (HWND hWnd, BOOL fErase)
|
|
{
|
|
MG_CHECK (MG_IS_NORMAL_WINDOW(hWnd));
|
|
|
|
if (fErase)
|
|
SendAsyncMessage (hWnd, MSG_CHANGESIZE, 0, 0);
|
|
|
|
SendAsyncMessage (hWnd, MSG_NCPAINT, 0, 0);
|
|
if (fErase)
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
else
|
|
InvalidateRect (hWnd, NULL, FALSE);
|
|
|
|
#if 0
|
|
#if 0
|
|
MSG Msg;
|
|
HWND hMainWnd;
|
|
|
|
/* MSG_PAINT Must Use PostMessage. Becuse Only PostMessage can give a correct order
|
|
* when processing MSG_PAINT message
|
|
*
|
|
* the Order of MSG_PAINT:
|
|
* * The Parent Window Must Be Painted before Children
|
|
* * The Previously created window must be Painted before afterwards created
|
|
*
|
|
* */
|
|
if (hWnd != HWND_DESKTOP) {
|
|
PMAINWIN pWin;
|
|
|
|
pWin = (PMAINWIN) hWnd;
|
|
SendMessage (hWnd, MSG_PAINT, 0, (LPARAM)(&pWin->InvRgn.rgn));
|
|
}
|
|
else
|
|
SendMessage (hWnd, MSG_PAINT, 0, 0);
|
|
|
|
#else
|
|
hMainWnd = GetMainWindowHandle(hWnd);
|
|
while(PeekMessageEx(&Msg, hMainWnd, MSG_PAINT, MSG_PAINT + 1 , FALSE, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&Msg);
|
|
DispatchMessage(&Msg);
|
|
}
|
|
#endif
|
|
#else /* a new implementation only check the window and its children. */
|
|
{
|
|
PMAINWIN pWin, winStartToUpdate;
|
|
|
|
winStartToUpdate = pWin = (PMAINWIN) hWnd;
|
|
while (pWin != pWin->pMainWin) {
|
|
if ((pWin->dwExStyle & WS_EX_TRANSPARENT)) {
|
|
winStartToUpdate = (PMAINWIN) pWin->hParent;
|
|
}
|
|
pWin = (PMAINWIN) pWin->hParent;
|
|
}
|
|
|
|
while ((hWnd = kernel_CheckInvalidRegion (winStartToUpdate))) {
|
|
pWin = (PMAINWIN) hWnd;
|
|
SendMessage (hWnd, MSG_PAINT, 0, (LPARAM)(&pWin->InvRgn.rgn));
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void GUIAPI UpdateInvalidClient (HWND hWnd, BOOL fErase)
|
|
{
|
|
MG_CHECK (MG_IS_NORMAL_WINDOW(hWnd));
|
|
|
|
if (fErase) {
|
|
SendAsyncMessage (hWnd, MSG_CHANGESIZE, 0, 0);
|
|
SendAsyncMessage (hWnd, MSG_NCPAINT, 0, 0);
|
|
}
|
|
|
|
/* a new implementation only check the window and its children. */
|
|
{
|
|
PMAINWIN pWin, winStartToUpdate;
|
|
|
|
winStartToUpdate = pWin = (PMAINWIN) hWnd;
|
|
while (pWin != pWin->pMainWin) {
|
|
if ((pWin->dwExStyle & WS_EX_TRANSPARENT)) {
|
|
winStartToUpdate = (PMAINWIN) pWin->hParent;
|
|
}
|
|
pWin = (PMAINWIN) pWin->hParent;
|
|
}
|
|
|
|
while ((hWnd = kernel_CheckInvalidRegion (winStartToUpdate))) {
|
|
pWin = (PMAINWIN) hWnd;
|
|
SendMessage (hWnd, MSG_PAINT, 0, (LPARAM)(&pWin->InvRgn.rgn));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** this function show window in behavious by specified iCmdShow.
|
|
** if the window was previously visible, the return value is nonzero.
|
|
** if the window was previously hiddedn, the return value is zero.
|
|
*/
|
|
BOOL GUIAPI ShowWindow (HWND hWnd, int iCmdShow)
|
|
{
|
|
//
|
|
//PrintInvRgn((PMAINWIN)hWnd, 0);
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
|
|
if (IsMainWindow (hWnd)) {
|
|
switch (iCmdShow) {
|
|
case SW_SHOWNORMAL:
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_MOVETOTOPMOST, (WPARAM)hWnd, 0);
|
|
break;
|
|
|
|
case SW_SHOW:
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_SHOWMAINWIN, (WPARAM)hWnd, 0);
|
|
break;
|
|
|
|
case SW_HIDE:
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_HIDEMAINWIN, (WPARAM)hWnd, 0);
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
PCONTROL pControl;
|
|
|
|
pControl = (PCONTROL)hWnd;
|
|
|
|
if (pControl->dwExStyle & WS_EX_CTRLASMAINWIN) {
|
|
if (iCmdShow == SW_SHOW)
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_SHOWGLOBALCTRL, (WPARAM)hWnd, iCmdShow);
|
|
else if (iCmdShow == SW_HIDE)
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_HIDEGLOBALCTRL, (WPARAM)hWnd, iCmdShow);
|
|
else {
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
switch (iCmdShow) {
|
|
case SW_SHOWNORMAL:
|
|
case SW_SHOW:
|
|
if (!(pControl->dwStyle & WS_VISIBLE)) {
|
|
pControl->dwStyle |= WS_VISIBLE;
|
|
|
|
SendAsyncMessage (hWnd, MSG_NCPAINT, 0, 0);
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
break;
|
|
|
|
case SW_HIDE:
|
|
if (pControl->dwStyle & WS_VISIBLE) {
|
|
|
|
pControl->dwStyle &= ~WS_VISIBLE;
|
|
InvalidateRect ((HWND)(pControl->pParent),
|
|
(RECT*)(&pControl->left), TRUE);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (iCmdShow == SW_HIDE && pControl->pParent->active == pControl) {
|
|
SendNotifyMessage (hWnd, MSG_KILLFOCUS, 0, 0);
|
|
pControl->pParent->active = NULL;
|
|
}
|
|
}
|
|
|
|
SendNotifyMessage (hWnd, MSG_SHOWWINDOW, (WPARAM)iCmdShow, 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI EnableWindow (HWND hWnd, BOOL fEnable)
|
|
{
|
|
BOOL fOldStatus;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
|
|
if (IsMainWindow (hWnd)) {
|
|
fOldStatus = SendMessage (HWND_DESKTOP, MSG_ENABLEMAINWIN,
|
|
(WPARAM)hWnd, (LPARAM)fEnable);
|
|
}
|
|
else {
|
|
PCONTROL pControl;
|
|
|
|
pControl = (PCONTROL)hWnd;
|
|
|
|
fOldStatus = !(pControl->dwStyle & WS_DISABLED);
|
|
}
|
|
|
|
SendNotifyMessage (hWnd, MSG_ENABLE, fEnable, 0);
|
|
|
|
return fOldStatus;
|
|
}
|
|
|
|
BOOL GUIAPI IsWindowEnabled (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hWnd;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
|
|
return !(pWin->dwStyle & WS_DISABLED);
|
|
}
|
|
|
|
void GUIAPI ScreenToClient (HWND hWnd, int* x, int* y)
|
|
{
|
|
PCONTROL pParent;
|
|
PCONTROL pCtrl;
|
|
|
|
MG_CHECK (MG_IS_NORMAL_WINDOW(hWnd));
|
|
pParent = pCtrl = MG_GET_CONTROL_PTR (hWnd);
|
|
|
|
*x -= pCtrl->cl;
|
|
*y -= pCtrl->ct;
|
|
while ((pParent = pParent->pParent)) {
|
|
*x -= pParent->cl;
|
|
*y -= pParent->ct;
|
|
}
|
|
}
|
|
|
|
void GUIAPI ClientToScreen(HWND hWnd, int* x, int* y)
|
|
{
|
|
PCONTROL pParent;
|
|
PCONTROL pCtrl;
|
|
|
|
MG_CHECK (MG_IS_NORMAL_WINDOW(hWnd));
|
|
pParent = pCtrl = MG_GET_CONTROL_PTR (hWnd);
|
|
|
|
*x += pCtrl->cl;
|
|
*y += pCtrl->ct;
|
|
while ((pParent = pParent->pParent)) {
|
|
*x += pParent->cl;
|
|
*y += pParent->ct;
|
|
}
|
|
}
|
|
|
|
void GUIAPI ScreenToWindow (HWND hWnd, int* x, int* y)
|
|
{
|
|
PCONTROL pParent;
|
|
PCONTROL pCtrl;
|
|
|
|
MG_CHECK (MG_IS_NORMAL_WINDOW(hWnd));
|
|
pParent = pCtrl = MG_GET_CONTROL_PTR (hWnd);
|
|
|
|
*x -= pCtrl->left;
|
|
*y -= pCtrl->top;
|
|
while ((pParent = pParent->pParent)) {
|
|
*x -= pParent->left;
|
|
*y -= pParent->top;
|
|
}
|
|
}
|
|
|
|
void GUIAPI WindowToClient (HWND hWnd, int* x, int* y)
|
|
{
|
|
PCONTROL pCtrl;
|
|
|
|
MG_CHECK (MG_IS_NORMAL_WINDOW(hWnd));
|
|
pCtrl = MG_GET_CONTROL_PTR (hWnd);
|
|
|
|
*x -= pCtrl->cl - pCtrl->left;
|
|
*y -= pCtrl->ct - pCtrl->top;
|
|
}
|
|
|
|
void GUIAPI ClientToWindow (HWND hWnd, int* x, int* y)
|
|
{
|
|
PCONTROL pCtrl;
|
|
|
|
MG_CHECK (MG_IS_NORMAL_WINDOW(hWnd));
|
|
pCtrl = MG_GET_CONTROL_PTR (hWnd);
|
|
|
|
*x += pCtrl->cl - pCtrl->left;
|
|
*y += pCtrl->ct - pCtrl->top;
|
|
}
|
|
|
|
void GUIAPI WindowToScreen (HWND hWnd, int* x, int* y)
|
|
{
|
|
PCONTROL pParent;
|
|
PCONTROL pCtrl;
|
|
|
|
MG_CHECK (MG_IS_NORMAL_WINDOW(hWnd));
|
|
pParent = pCtrl = MG_GET_CONTROL_PTR (hWnd);
|
|
|
|
*x += pCtrl->left;
|
|
*y += pCtrl->top;
|
|
while ((pParent = pParent->pParent)) {
|
|
*x += pParent->left;
|
|
*y += pParent->top;
|
|
}
|
|
}
|
|
|
|
BOOL GUIAPI GetClientRect (HWND hWnd, PRECT prc)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hWnd;
|
|
|
|
if (hWnd == HWND_DESKTOP) {
|
|
*prc = g_rcScr;
|
|
return TRUE;
|
|
}
|
|
else if (hWnd == HWND_INVALID || pWin->DataType != TYPE_HWND)
|
|
return FALSE;
|
|
|
|
prc->left = prc->top = 0;
|
|
prc->right = pWin->cr - pWin->cl;
|
|
prc->bottom = pWin->cb - pWin->ct;
|
|
return TRUE;
|
|
}
|
|
|
|
/******************** main window and control styles support *****************/
|
|
/* Since 4.2.0. */
|
|
gal_pixel GUIAPI DWORD2PixelByWindow (HWND hWnd, DWORD dwColor)
|
|
{
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
PMAINWIN pWin = (PMAINWIN)hWnd;
|
|
if (hWnd == HWND_NULL || hWnd == HWND_DESKTOP || hWnd == HWND_INVALID) {
|
|
return DWORD2Pixel (HDC_SCREEN, dwColor);
|
|
}
|
|
|
|
return GAL_MapRGBA (pWin->surf->format,
|
|
GetRValue (dwColor), GetGValue (dwColor),
|
|
GetBValue (dwColor), GetAValue (dwColor));
|
|
#else
|
|
return DWORD2Pixel (HDC_SCREEN, dwColor);
|
|
#endif
|
|
}
|
|
|
|
gal_pixel GUIAPI GetWindowBkColor (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin = (PMAINWIN)hWnd;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), PIXEL_invalid);
|
|
|
|
return pWin->iBkColor;
|
|
}
|
|
|
|
gal_pixel GUIAPI SetWindowBkColor (HWND hWnd, gal_pixel new_bkcolor)
|
|
{
|
|
gal_pixel old_bkcolor;
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), PIXEL_invalid);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
old_bkcolor = pWin->iBkColor;
|
|
pWin->iBkColor = new_bkcolor;
|
|
return old_bkcolor;
|
|
}
|
|
|
|
PLOGFONT GUIAPI GetWindowFont (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), NULL);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return pWin->pLogFont;
|
|
}
|
|
|
|
PLOGFONT GUIAPI SetWindowFont (HWND hWnd, PLOGFONT pLogFont)
|
|
{
|
|
PLOGFONT old_logfont;
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), NULL);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if (pLogFont == NULL)
|
|
pLogFont = GetSystemFont (SYSLOGFONT_WCHAR_DEF);
|
|
|
|
if (SendMessage (hWnd, MSG_FONTCHANGING, 0, (LPARAM)pLogFont))
|
|
return NULL;
|
|
|
|
old_logfont = pWin->pLogFont;
|
|
pWin->pLogFont = pLogFont;
|
|
SendNotifyMessage (hWnd, MSG_FONTCHANGED, 0, 0);
|
|
|
|
return old_logfont;
|
|
}
|
|
|
|
HCURSOR GUIAPI GetWindowCursor (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return pWin->hCursor;
|
|
}
|
|
|
|
HCURSOR GUIAPI SetWindowCursor (HWND hWnd, HCURSOR hNewCursor)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if (pWin->WinType == TYPE_MAINWIN)
|
|
return (HCURSOR)SendMessage (HWND_DESKTOP,
|
|
MSG_SETWINCURSOR, (WPARAM)hWnd, (LPARAM)hNewCursor);
|
|
else if (pWin->WinType == TYPE_CONTROL) {
|
|
HCURSOR old = pWin->hCursor;
|
|
pWin->hCursor = hNewCursor;
|
|
return old;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD GetWindowStyle (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return pWin->dwStyle;
|
|
}
|
|
|
|
BOOL GUIAPI ExcludeWindowStyle (HWND hWnd, DWORD dwStyle)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
pWin->dwStyle &= ~dwStyle;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI IncludeWindowStyle (HWND hWnd, DWORD dwStyle)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
pWin->dwStyle |= dwStyle;
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD GetWindowExStyle (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return pWin->dwExStyle;
|
|
}
|
|
|
|
BOOL GUIAPI ExcludeWindowExStyle (HWND hWnd, DWORD dwStyle)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
pWin->dwExStyle &= ~dwStyle;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI IncludeWindowExStyle (HWND hWnd, DWORD dwStyle)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
pWin->dwExStyle |= dwStyle;
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD GUIAPI GetWindowAdditionalData (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return pWin->dwAddData;
|
|
}
|
|
|
|
DWORD GUIAPI SetWindowAdditionalData (HWND hWnd, DWORD newData)
|
|
{
|
|
DWORD oldOne;
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0L);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
oldOne = pWin->dwAddData;
|
|
pWin->dwAddData = newData;
|
|
return oldOne;
|
|
}
|
|
|
|
DWORD GUIAPI GetWindowAdditionalData2 (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0L);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return pWin->dwAddData2;
|
|
}
|
|
|
|
DWORD GUIAPI SetWindowAdditionalData2 (HWND hWnd, DWORD newData)
|
|
{
|
|
DWORD oldOne;
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0L);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
oldOne = pWin->dwAddData2;
|
|
pWin->dwAddData2 = newData;
|
|
return oldOne;
|
|
}
|
|
|
|
DWORD GUIAPI GetWindowClassAdditionalData (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
PCONTROL pCtrl;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if (pWin->WinType == TYPE_CONTROL) {
|
|
pCtrl = MG_GET_CONTROL_PTR(hWnd);
|
|
return pCtrl->pcci->dwAddData;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD GUIAPI SetWindowClassAdditionalData (HWND hWnd, DWORD newData)
|
|
{
|
|
PMAINWIN pWin;
|
|
PCONTROL pCtrl;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), 0);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if (pWin->WinType == TYPE_CONTROL) {
|
|
DWORD oldOne;
|
|
|
|
pCtrl = MG_GET_CONTROL_PTR(hWnd);
|
|
oldOne = pCtrl->pcci->dwAddData;
|
|
pCtrl->pcci->dwAddData = newData;
|
|
return oldOne;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
const char* GUIAPI GetClassName (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
PCONTROL pCtrl;
|
|
|
|
pWin = (PMAINWIN)hWnd;
|
|
|
|
if (!MG_IS_WINDOW(hWnd))
|
|
return NULL;
|
|
else if (hWnd == HWND_DESKTOP)
|
|
return ROOTWINCLASSNAME;
|
|
else if (pWin->WinType == TYPE_MAINWIN)
|
|
return MAINWINCLASSNAME;
|
|
else if (pWin->WinType == TYPE_CONTROL) {
|
|
pCtrl = (PCONTROL)hWnd;
|
|
return pCtrl->pcci->name;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
BOOL GUIAPI IsWindowVisible (HWND hWnd)
|
|
{
|
|
PMAINWIN pMainWin;
|
|
PCONTROL pCtrl;
|
|
|
|
if ((pMainWin = gui_CheckAndGetMainWindowPtr (hWnd))) {
|
|
return pMainWin->dwStyle & WS_VISIBLE;
|
|
}
|
|
else if (IsControl (hWnd)) {
|
|
pCtrl = (PCONTROL)hWnd;
|
|
while (pCtrl) {
|
|
if (!(pCtrl->dwStyle & WS_VISIBLE))
|
|
return FALSE;
|
|
|
|
pCtrl = pCtrl->pParent;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI GetWindowRect (HWND hWnd, PRECT prc)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
prc->left = pWin->left;
|
|
prc->top = pWin->top;
|
|
prc->right = pWin->right;
|
|
prc->bottom = pWin->bottom;
|
|
return TRUE;
|
|
}
|
|
|
|
WNDPROC GUIAPI GetWindowCallbackProc (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), NULL);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return pWin->MainWindowProc;
|
|
}
|
|
|
|
WNDPROC GUIAPI SetWindowCallbackProc (HWND hWnd, WNDPROC newProc)
|
|
{
|
|
PMAINWIN pWin;
|
|
WNDPROC old_proc;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), NULL);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
old_proc = pWin->MainWindowProc;
|
|
if (newProc)
|
|
pWin->MainWindowProc = newProc;
|
|
return old_proc;
|
|
}
|
|
|
|
const char* GUIAPI GetWindowCaption (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), NULL);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
return pWin->spCaption;
|
|
}
|
|
|
|
BOOL GUIAPI SetWindowCaption (HWND hWnd, const char* spCaption)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if (pWin->WinType == TYPE_MAINWIN) {
|
|
return SetWindowText (hWnd, spCaption);
|
|
}
|
|
else if (pWin->WinType == TYPE_CONTROL) {
|
|
PCONTROL pCtrl;
|
|
pCtrl = (PCONTROL)hWnd;
|
|
if (pCtrl->spCaption) {
|
|
FreeFixStr (pCtrl->spCaption);
|
|
pCtrl->spCaption = NULL;
|
|
}
|
|
|
|
if (spCaption) {
|
|
pCtrl->spCaption = FixStrAlloc (strlen (spCaption));
|
|
if (spCaption [0])
|
|
strcpy (pCtrl->spCaption, spCaption);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
int GUIAPI GetWindowTextLength (HWND hWnd)
|
|
{
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), -1);
|
|
|
|
return SendMessage (hWnd, MSG_GETTEXTLENGTH, 0, 0);
|
|
}
|
|
|
|
int GUIAPI GetWindowText (HWND hWnd, char* spString, int nMaxLen)
|
|
{
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), -1);
|
|
|
|
return SendMessage (hWnd, MSG_GETTEXT, (WPARAM)nMaxLen, (LPARAM)spString);
|
|
}
|
|
|
|
BOOL GUIAPI SetWindowText (HWND hWnd, const char* spString)
|
|
{
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
|
|
return (SendMessage (hWnd, MSG_SETTEXT, 0, (LPARAM)spString) == 0);
|
|
}
|
|
|
|
extern BLOCKHEAP __mg_FreeClipRectList;
|
|
/* NOTE: This function is control safe */
|
|
BOOL GUIAPI MoveWindow (HWND hWnd, int x, int y, int w, int h, BOOL fPaint)
|
|
{
|
|
RECT rcWindow;
|
|
RECT rcExpect, rcResult;
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
SetRect (&rcExpect, x, y, x + w, y + h);
|
|
|
|
GetWindowRect (hWnd, &rcWindow);
|
|
SendMessage (hWnd, MSG_SIZECHANGING,
|
|
(WPARAM)(&rcExpect), (LPARAM)(&rcResult));
|
|
|
|
if (EqualRect (&rcWindow, &rcResult)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (IsMainWindow (hWnd) || (pWin->dwExStyle & WS_EX_CTRLASMAINWIN)) {
|
|
// Since 4.2.0: check the return value.
|
|
if (SendMessage (HWND_DESKTOP, MSG_MOVEMAINWIN,
|
|
(WPARAM)hWnd, (LPARAM)(&rcResult)))
|
|
return FALSE;
|
|
|
|
if (RECTH (rcWindow) != RECTH (rcResult)
|
|
|| RECTW (rcWindow) != RECTW (rcResult)) {
|
|
fPaint = TRUE;
|
|
}
|
|
}
|
|
else {
|
|
PCONTROL pParent;
|
|
PCONTROL pCtrl;
|
|
|
|
pCtrl = (PCONTROL)hWnd;
|
|
pParent = pCtrl->pParent;
|
|
|
|
rcExpect = rcResult;
|
|
SendMessage (hWnd, MSG_CHANGESIZE,
|
|
(WPARAM)(&rcExpect), (LPARAM)(&rcResult));
|
|
|
|
if (IsWindowVisible (hWnd)
|
|
&& (pParent->InvRgn.frozen == 0)) {
|
|
|
|
#if 1
|
|
InvalidateRect((HWND)pParent, &rcWindow, TRUE);
|
|
InvalidateRect((HWND)pParent, &rcResult, TRUE);
|
|
#elif 0
|
|
if (pCtrl->dwExStyle & WS_EX_TRANSPARENT)
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
else {
|
|
HDC hdc;
|
|
hdc = get_valid_dc ((PMAINWIN)pParent, TRUE);
|
|
BitBlt (hdc, pCtrl->left, pCtrl->top,
|
|
pCtrl->right - pCtrl->left,
|
|
pCtrl->bottom - pCtrl->top,
|
|
hdc, rcResult.left, rcResult.top, 0);
|
|
release_valid_dc ((PMAINWIN)pParent, hdc);
|
|
}
|
|
/* set to invisible temporarily. */
|
|
/* FIXME: need more optimization. */
|
|
pCtrl->dwStyle &= ~WS_VISIBLE;
|
|
InvalidateRect ((HWND)pParent, &rcWindow, TRUE);
|
|
rcExpect.left = rcResult.left;
|
|
rcExpect.top = rcResult.top;
|
|
rcExpect.right = rcResult.left + RECTW (rcWindow);
|
|
rcExpect.bottom = rcResult.top + RECTH (rcWindow);
|
|
InvalidateRect ((HWND)pParent, &rcExpect, TRUE);
|
|
pCtrl->dwStyle |= WS_VISIBLE;
|
|
#else
|
|
if (pCtrl->dwExStyle & WS_EX_TRANSPARENT) {
|
|
InvalidateRect ((HWND)pParent, &rcWindow, TRUE);
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
else {
|
|
if (DoesIntersect ((const RECT*)&rcWindow, (const RECT*)&pCtrl->cl)) {
|
|
CLIPRGN rgn;
|
|
PCLIPRECT p = NULL;
|
|
InitClipRgn (&rgn, &__mg_FreeClipRectList);
|
|
AddClipRect (&rgn, &rcWindow);
|
|
SubtractClipRect (&rgn, (const RECT*)&pCtrl->cl);
|
|
p = rgn.head;
|
|
while(p) {
|
|
InvalidateRect((HWND)pParent, &p->rc, TRUE);
|
|
p = p->next;
|
|
}
|
|
EmptyClipRgn (&rgn);
|
|
}
|
|
else {
|
|
InvalidateRect ((HWND)pParent, &rcWindow, TRUE);
|
|
}
|
|
if (RECTH (rcWindow) != RECTH (rcResult)
|
|
|| RECTW (rcWindow) != RECTW (rcResult))
|
|
{
|
|
fPaint = TRUE;
|
|
}
|
|
else {
|
|
PCONTROL pChild ;
|
|
RECT rc;
|
|
BOOL flag = TRUE;
|
|
|
|
for (pChild = pParent->children; pChild; pChild = pChild->next) {
|
|
if (pChild == pCtrl || !(pChild->dwStyle & WS_VISIBLE)
|
|
|| (pChild->dwExStyle & WS_EX_CTRLASMAINWIN))
|
|
continue;
|
|
|
|
if(IntersectRect(&rc, &rcWindow, (const RECT*)&pChild->cl)) {
|
|
flag = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (!flag) {
|
|
InvalidateRect ((HWND)pParent, &rcResult, FALSE);
|
|
}
|
|
else {
|
|
HDC hdc;
|
|
hdc = get_valid_dc ((PMAINWIN)pParent, TRUE);
|
|
BitBlt (hdc, rcWindow.left, rcWindow.top,
|
|
RECTW(rcWindow), RECTH(rcWindow),
|
|
hdc, rcResult.left, rcResult.top, 0);
|
|
release_valid_dc ((PMAINWIN)pParent, hdc);
|
|
|
|
for(pChild = pCtrl->next; pChild; pChild = pChild->next) {
|
|
if(!(pChild->dwStyle & WS_VISIBLE)
|
|
|| (pChild->dwExStyle & WS_EX_CTRLASMAINWIN))
|
|
continue;
|
|
|
|
if(IntersectRect(&rc, &rcResult, (const RECT*)&pChild->cl)) {
|
|
OffsetRect(&rc, - pChild->left, - pChild->top);
|
|
InvalidateRect((HWND)pChild, &rc, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if ((RECTW (rcWindow) != w ) || (RECTH (rcWindow) != h))
|
|
SendAsyncMessage (hWnd, MSG_NCPAINT, 0, 0);
|
|
if (fPaint) {
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************** Paint support ***********************************/
|
|
|
|
#define WIRM_PARENT 0x01
|
|
#define WIRM_PREV_SIBLING 0x02
|
|
#define WIRM_NEXT_SIBLING 0x04
|
|
#define WIRM_CHILDREN 0x08
|
|
#define WIRM_SIBLING (WIRM_PREV_SIBLING|WIRM_NEXT_SIBLING)
|
|
#define WIRM_ALL (WIRM_PARENT | WIRM_CHILDREN | WIRM_SIBLING)
|
|
static BOOL _wndInvalidateRect(HWND hWnd, const RECT* prc, BOOL bEraseBkgnd, int mark)
|
|
{
|
|
PCONTROL pCtrl;
|
|
RECT rcClient;
|
|
RECT rcInv;
|
|
RECT rcTemp;
|
|
PINVRGN pInvRgn;
|
|
|
|
|
|
pCtrl = (PCONTROL)hWnd;
|
|
|
|
|
|
//invalidate itself
|
|
rcClient.left = rcClient.top = 0;
|
|
rcClient.right = pCtrl->cr - pCtrl->cl;
|
|
rcClient.bottom = pCtrl->cb - pCtrl->ct;
|
|
|
|
pInvRgn = &pCtrl->InvRgn;
|
|
|
|
if(!pInvRgn->frozen)
|
|
{
|
|
PCONTROL pNext;
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_lock(&pInvRgn->lock);
|
|
#endif
|
|
if (bEraseBkgnd) {
|
|
pCtrl->Flags |= WF_ERASEBKGND;
|
|
}
|
|
|
|
if(prc) {
|
|
rcInv = *prc;
|
|
NormalizeRect(&rcInv);
|
|
if(IntersectRect(&rcInv, &rcInv, &rcClient))
|
|
AddClipRect(&pInvRgn->rgn, &rcInv);
|
|
}
|
|
else {
|
|
rcInv = rcClient;
|
|
SetClipRgn(&pInvRgn->rgn, &rcInv);
|
|
}
|
|
|
|
rcTemp = rcInv;
|
|
OffsetRect(&rcTemp, pCtrl->cl, pCtrl->ct);
|
|
|
|
//subtract from next sibling controls
|
|
if(pCtrl->WinType == TYPE_CONTROL /*&& ( mark & WIRM_NEXT_SIBLING)*/)
|
|
{
|
|
for(pNext = pCtrl->next; pNext; pNext = pNext->next)
|
|
{
|
|
RECT rc;
|
|
if((pNext->dwStyle & WS_VISIBLE)
|
|
&& !(pNext->dwExStyle & WS_EX_TRANSPARENT)
|
|
&& IntersectRect(&rc, &rcTemp, (const RECT*)&pNext->left))
|
|
{
|
|
OffsetRect(&rc, - pCtrl->cl, - pCtrl->ct );
|
|
SubtractClipRect(&pInvRgn->rgn, &rc);
|
|
}
|
|
}
|
|
}
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_unlock(&pInvRgn->lock);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//invalidate parent
|
|
if( (mark & WIRM_PARENT)
|
|
&& (pCtrl->dwExStyle & WS_EX_TRANSPARENT)
|
|
&& pCtrl->WinType != TYPE_MAINWIN
|
|
&& !(pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN))
|
|
{
|
|
/* houhh 20100426, invalide rect for parent must be valid. */
|
|
if (rcTemp.top < rcTemp.bottom && rcTemp.left < rcTemp.right) {
|
|
_wndInvalidateRect((HWND)pCtrl->pParent, &rcTemp, bEraseBkgnd, WIRM_PARENT|WIRM_SIBLING);
|
|
}
|
|
}
|
|
|
|
//invalidate sibling
|
|
if(pCtrl->WinType==TYPE_CONTROL
|
|
&& (pCtrl->dwExStyle & WS_EX_TRANSPARENT)
|
|
&& !(pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN)
|
|
&& (mark & WIRM_PREV_SIBLING))
|
|
{
|
|
PCONTROL pPrev;
|
|
for(pPrev = pCtrl->prev; pPrev; pPrev = pPrev->prev)
|
|
{
|
|
RECT rc;
|
|
|
|
if(!(pPrev->dwStyle & WS_VISIBLE))
|
|
continue;
|
|
|
|
if(IntersectRect(&rc, &rcTemp, (const RECT*)&pPrev->cl))
|
|
{
|
|
OffsetRect(&rc, - pPrev->cl, - pPrev->ct);
|
|
_wndInvalidateRect((HWND)pPrev, &rc, bEraseBkgnd, WIRM_CHILDREN);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pCtrl->WinType==TYPE_CONTROL
|
|
&& !(pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN)
|
|
&& (mark & WIRM_NEXT_SIBLING))
|
|
{
|
|
PCONTROL pNext;
|
|
for(pNext = pCtrl->next; pNext; pNext = pNext->next)
|
|
{
|
|
RECT rc;
|
|
if(!(pNext->dwStyle & WS_VISIBLE)
|
|
|| !(pNext->dwExStyle & WS_EX_TRANSPARENT))
|
|
continue;
|
|
|
|
if(IntersectRect(&rc, &rcTemp, (const RECT*)&pNext->cl))
|
|
{
|
|
OffsetRect(&rc, - pNext->cl, - pNext->ct);
|
|
_wndInvalidateRect((HWND)pNext, &rc, bEraseBkgnd, WIRM_CHILDREN);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//check mark for invalidate children
|
|
if(mark & WIRM_CHILDREN)
|
|
{
|
|
PCONTROL pChild ;
|
|
RECT rc;
|
|
|
|
|
|
for(pChild = pCtrl->children; pChild; pChild = pChild->next)
|
|
{
|
|
if(!(pChild->dwStyle & WS_VISIBLE)
|
|
|| (pChild->dwExStyle & WS_EX_CTRLASMAINWIN))
|
|
continue;
|
|
|
|
if(IntersectRect(&rc, &rcInv, (const RECT*)&pChild->cl))
|
|
{
|
|
OffsetRect(&rc, - pChild->cl, - pChild->ct);
|
|
_wndInvalidateRect((HWND)pChild, &rc, bEraseBkgnd, WIRM_CHILDREN);
|
|
}
|
|
if(IntersectRect(&rc, &rcInv, (const RECT*)&pChild->left))
|
|
{
|
|
OffsetRect(&rc, - pChild->left, - pChild->top);
|
|
SendAsyncMessage((HWND)pChild, MSG_NCPAINT, 0, (LPARAM)&rc);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOL GUIAPI InvalidateRect (HWND hWnd, const RECT* prc, BOOL bEraseBkgnd)
|
|
{
|
|
BOOL retval;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
|
|
retval = _wndInvalidateRect(hWnd, prc, bEraseBkgnd, WIRM_ALL);
|
|
PostMessage (hWnd, MSG_PAINT, 0, (LPARAM)prc);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/* TODO: Optimize */
|
|
BOOL GUIAPI InvalidateRegion (HWND hWnd, const CLIPRGN* pRgn, BOOL bErase)
|
|
{
|
|
const CLIPRECT* crc = pRgn->head;
|
|
|
|
while (crc) {
|
|
if (!InvalidateRect (hWnd, &crc->rc, bErase))
|
|
return FALSE;
|
|
crc = crc->next;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI ValidateRect (HWND hWnd, const RECT* rect)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if (rect) {
|
|
return SubtractClipRect (&pWin->InvRgn.rgn, rect);
|
|
}
|
|
else {
|
|
EmptyClipRgn (&pWin->InvRgn.rgn);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI ValidateRegion (HWND hWnd, const CLIPRGN* pRgn)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if (pRgn) {
|
|
return SubtractRegion (&pWin->InvRgn.rgn, &pWin->InvRgn.rgn, pRgn);
|
|
}
|
|
else {
|
|
EmptyClipRgn (&pWin->InvRgn.rgn);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL GUIAPI GetUpdateRect (HWND hWnd, RECT* update_rect)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
*update_rect = pWin->InvRgn.rgn.rcBound;
|
|
return TRUE;
|
|
}
|
|
|
|
int GUIAPI GetUpdateRegion (HWND hWnd, PCLIPRGN pRgn)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK_RET (pRgn != NULL, -1);
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), -1);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
CopyRegion (pRgn, &pWin->InvRgn.rgn);
|
|
return pRgn->type;
|
|
}
|
|
|
|
HDC GUIAPI BeginPaint (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
PINVRGN pInvRgn;
|
|
HDC hdc;
|
|
RECT rcInv;
|
|
PCONTROL child;
|
|
BOOL fEraseBk;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), HDC_INVALID);
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
|
|
if (pWin->pCaretInfo && pWin->pCaretInfo->fBlink) {
|
|
HideCaretEx (hWnd, FALSE);
|
|
pWin->pCaretInfo->fBlink = TRUE;
|
|
}
|
|
|
|
hdc = get_valid_dc (pWin, TRUE);
|
|
|
|
#if 0
|
|
/* FIXME: why do this? */
|
|
if (((PMAINWIN)hWnd)->dwExStyle & WS_EX_TRANSPARENT)
|
|
SetBkMode (hdc, BM_TRANSPARENT);
|
|
#endif
|
|
|
|
pInvRgn = &pWin->InvRgn;
|
|
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_lock (&pInvRgn->lock);
|
|
#endif
|
|
pInvRgn->frozen ++;
|
|
|
|
fEraseBk = pWin->Flags & WF_ERASEBKGND;
|
|
pWin->Flags = (pWin->Flags & ~WF_ERASEBKGND);
|
|
|
|
SelectClipRegion (hdc, &pInvRgn->rgn);
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
CopyRect (&pWin->pMainWin->update_rc, &(dc_HDC2PDC(hdc))->ecrgn.rcBound);
|
|
coor_SP2DP((PDC)hdc, &pWin->pMainWin->update_rc.left,
|
|
&pWin->pMainWin->update_rc.top);
|
|
coor_SP2DP((PDC)hdc, &pWin->pMainWin->update_rc.right,
|
|
&pWin->pMainWin->update_rc.bottom);
|
|
}
|
|
else {
|
|
CopyRect (&pWin->pMainWin->update_rc, &pInvRgn->rgn.rcBound);
|
|
}
|
|
rcInv = pInvRgn->rgn.rcBound;
|
|
|
|
EmptyClipRgn (&pInvRgn->rgn);
|
|
|
|
pInvRgn->frozen --;
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_unlock (&pInvRgn->lock);
|
|
#endif
|
|
|
|
if(!(pWin->dwStyle & WS_VISIBLE))
|
|
return hdc;
|
|
|
|
/* exclude the children area from the client */
|
|
/* if (pWin->dwExStyle & WS_EX_CLIPCHILDREN)*/ {
|
|
child = (PCONTROL)pWin->hFirstChild;
|
|
while (child) {
|
|
if ((child->dwStyle & WS_VISIBLE) && !(child->dwExStyle & WS_EX_TRANSPARENT)
|
|
&& DoesIntersect ((const RECT*)&child->left, &rcInv)) {
|
|
ExcludeClipRect (hdc, (const RECT*)&child->left);
|
|
}
|
|
child = child->next;
|
|
}
|
|
}
|
|
//erase bkgnd
|
|
if(fEraseBk
|
|
&& !(pWin->WinType == TYPE_CONTROL
|
|
&& !(pWin->dwExStyle & WS_EX_CTRLASMAINWIN)
|
|
&& (pWin->dwExStyle & WS_EX_TRANSPARENT)
|
|
)
|
|
)
|
|
SendAsyncMessage(hWnd, MSG_ERASEBKGND, (WPARAM)hdc,0); //(LPARAM)&rcInv);
|
|
|
|
//repaint NC area of tranparent children
|
|
for(child = (PCONTROL)pWin->hFirstChild; child; child = child->next)
|
|
{
|
|
RECT rcTemp;
|
|
if(!(pWin->dwExStyle & WS_EX_TRANSPARENT)
|
|
&& (!(child->dwStyle & WS_VISIBLE)
|
|
|| !(child->dwExStyle & WS_EX_TRANSPARENT)
|
|
|| ( child->dwExStyle & WS_EX_CTRLASMAINWIN)))
|
|
continue;
|
|
|
|
if(IntersectRect(&rcTemp, &rcInv, (const RECT*)&child->left))
|
|
{
|
|
//draw NC
|
|
OffsetRect(&rcTemp, -child->left, -child->top);
|
|
SendAsyncMessage((HWND)child, MSG_NCPAINT, (WPARAM)0, (LPARAM)&rcTemp);
|
|
}
|
|
|
|
}
|
|
|
|
return hdc;
|
|
}
|
|
|
|
void GUIAPI EndPaint (HWND hWnd, HDC hdc)
|
|
{
|
|
PMAINWIN pWin;
|
|
|
|
MG_CHECK (MG_IS_NORMAL_WINDOW(hWnd));
|
|
pWin = MG_GET_WINDOW_PTR (hWnd);
|
|
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
if (!IsRectEmpty(&pWin->pMainWin->update_rc)) {
|
|
HDC real_dc = HDC_INVALID;
|
|
real_dc = GetClientDC ((HWND)pWin->pMainWin);
|
|
|
|
__mg_update_secondary_dc (pWin, hdc, real_dc,
|
|
&pWin->pMainWin->update_rc, HT_CLIENT);
|
|
ReleaseDC (real_dc);
|
|
}
|
|
}
|
|
|
|
release_valid_dc (pWin, hdc);
|
|
|
|
/* privCDC is not need Release, but need clear lcrgn.*/
|
|
if (pWin->dwExStyle & WS_EX_USEPRIVATECDC)
|
|
SelectClipRect (pWin->privCDC, NULL);
|
|
|
|
/* show caret */
|
|
#if 0
|
|
if (pWin->pCaretInfo) {
|
|
GetCaretBitmaps (pWin->pCaretInfo);
|
|
if (pWin->pCaretInfo->fBlink) {
|
|
HDC caret_dc = GetClientDC (hWnd);
|
|
pWin->pCaretInfo->fShow = TRUE;
|
|
pWin->pCaretInfo->caret_bmp.bmBits = pWin->pCaretInfo->pXored;
|
|
FillBoxWithBitmap (caret_dc,
|
|
pWin->pCaretInfo->x, pWin->pCaretInfo->y, 0, 0,
|
|
&pWin->pCaretInfo->caret_bmp);
|
|
ReleaseDC (caret_dc);
|
|
}
|
|
}
|
|
#else
|
|
if (pWin->pCaretInfo && pWin->pCaretInfo->fBlink) {
|
|
pWin->pCaretInfo->fBlink = FALSE;
|
|
ShowCaretEx (hWnd, FALSE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
BOOL RegisterWindowClass (PWNDCLASS pWndClass)
|
|
{
|
|
if (pWndClass == NULL)
|
|
return FALSE;
|
|
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_REGISTERWNDCLASS, 0, (LPARAM)pWndClass) == ERR_OK;
|
|
}
|
|
|
|
BOOL UnregisterWindowClass (const char* szClassName)
|
|
{
|
|
if (szClassName == NULL)
|
|
return FALSE;
|
|
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_UNREGISTERWNDCLASS, 0, (LPARAM)szClassName) == ERR_OK;
|
|
}
|
|
|
|
BOOL GUIAPI GetWindowClassInfo (PWNDCLASS pWndClass)
|
|
{
|
|
if (pWndClass == NULL || pWndClass->spClassName == NULL)
|
|
return FALSE;
|
|
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_CTRLCLASSDATAOP, CCDOP_GETCCI, (LPARAM)pWndClass) == ERR_OK;
|
|
}
|
|
|
|
BOOL GUIAPI SetWindowClassInfo (const WNDCLASS* pWndClass)
|
|
{
|
|
if (pWndClass == NULL || pWndClass->spClassName == NULL)
|
|
return FALSE;
|
|
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_CTRLCLASSDATAOP, CCDOP_SETCCI, (LPARAM)pWndClass) == ERR_OK;
|
|
}
|
|
|
|
static void set_control_renderer (PCONTROL pCtrl, const char* werdr_name)
|
|
{
|
|
const WINDOW_ELEMENT_RENDERER* renderer =
|
|
GetWindowRendererFromName (werdr_name);
|
|
|
|
if (renderer)
|
|
pCtrl->we_rdr = (WINDOW_ELEMENT_RENDERER*)renderer;
|
|
else
|
|
pCtrl->we_rdr = __mg_def_renderer;
|
|
|
|
if (pCtrl->we_rdr)
|
|
++pCtrl->we_rdr->refcount;
|
|
}
|
|
|
|
HWND GUIAPI CreateWindowEx2 (const char* spClassName,
|
|
const char* spCaption, DWORD dwStyle, DWORD dwExStyle,
|
|
LINT id, int x, int y, int w, int h, HWND hParentWnd,
|
|
const char* werdr_name, const WINDOW_ELEMENT_ATTR* we_attrs,
|
|
DWORD dwAddData)
|
|
{
|
|
PMAINWIN pMainWin;
|
|
PCTRLCLASSINFO cci;
|
|
PCONTROL pNewCtrl;
|
|
RECT rcExpect;
|
|
|
|
if (!(pMainWin = gui_GetMainWindowPtrOfControl (hParentWnd)))
|
|
return HWND_INVALID;
|
|
|
|
/* Since 4.2.0 */
|
|
if (dwExStyle & WS_EX_CTRLASMAINWIN &&
|
|
(pMainWin->dwExStyle & WS_EX_WINTYPE_MASK)) {
|
|
_WRN_PRINTF("Cannot create global controls in a special main window\n");
|
|
return HWND_INVALID;
|
|
}
|
|
|
|
cci = (PCTRLCLASSINFO)SendMessage (HWND_DESKTOP,
|
|
MSG_GETCTRLCLASSINFO, 0, (LPARAM)spClassName);
|
|
|
|
if (!cci) return HWND_INVALID;
|
|
|
|
pNewCtrl = calloc (1, sizeof (CONTROL));
|
|
|
|
if (!pNewCtrl) return HWND_INVALID;
|
|
|
|
pNewCtrl->DataType = TYPE_HWND;
|
|
pNewCtrl->WinType = TYPE_CONTROL;
|
|
|
|
pNewCtrl->left = x;
|
|
pNewCtrl->top = y;
|
|
pNewCtrl->right = x + w;
|
|
pNewCtrl->bottom = y + h;
|
|
|
|
memcpy (&pNewCtrl->cl, &pNewCtrl->left, sizeof (RECT));
|
|
memcpy (&rcExpect, &pNewCtrl->left, sizeof (RECT));
|
|
|
|
if (spCaption) {
|
|
int len = strlen (spCaption);
|
|
|
|
pNewCtrl->spCaption = FixStrAlloc (len);
|
|
if (len > 0)
|
|
strcpy (pNewCtrl->spCaption, spCaption);
|
|
}
|
|
else
|
|
pNewCtrl->spCaption = "";
|
|
|
|
pNewCtrl->dwStyle = dwStyle | WS_CHILD | cci->dwStyle;
|
|
pNewCtrl->dwExStyle = dwExStyle | cci->dwExStyle;
|
|
|
|
pNewCtrl->hCursor = cci->hCursor;
|
|
pNewCtrl->hMenu = 0;
|
|
pNewCtrl->hAccel = 0;
|
|
pNewCtrl->hIcon = 0;
|
|
pNewCtrl->hSysMenu = 0;
|
|
pNewCtrl->id = id;
|
|
pNewCtrl->pCaretInfo = NULL;
|
|
|
|
pNewCtrl->dwAddData = dwAddData;
|
|
pNewCtrl->dwAddData2 = 0;
|
|
|
|
pNewCtrl->ControlProc = cci->ControlProc;
|
|
|
|
/* Scroll bar */
|
|
if (pNewCtrl->dwStyle & WS_VSCROLL) {
|
|
pNewCtrl->vscroll.minPos = 0;
|
|
pNewCtrl->vscroll.maxPos = 100;
|
|
pNewCtrl->vscroll.curPos = 0;
|
|
pNewCtrl->vscroll.pageStep = 101;
|
|
pNewCtrl->vscroll.barStart = 0;
|
|
pNewCtrl->vscroll.barLen = 10;
|
|
pNewCtrl->vscroll.status = SBS_NORMAL;
|
|
}
|
|
else
|
|
pNewCtrl->vscroll.status = SBS_HIDE | SBS_DISABLED;
|
|
|
|
if (pNewCtrl->dwStyle & WS_HSCROLL) {
|
|
pNewCtrl->hscroll.minPos = 0;
|
|
pNewCtrl->hscroll.maxPos = 100;
|
|
pNewCtrl->hscroll.curPos = 0;
|
|
pNewCtrl->hscroll.pageStep = 101;
|
|
pNewCtrl->hscroll.barStart = 0;
|
|
pNewCtrl->hscroll.barLen = 10;
|
|
pNewCtrl->hscroll.status = SBS_NORMAL;
|
|
}
|
|
else
|
|
pNewCtrl->hscroll.status = SBS_HIDE | SBS_DISABLED;
|
|
|
|
/** prefer to use parent renderer */
|
|
if (pNewCtrl->dwExStyle & WS_EX_USEPARENTRDR) {
|
|
if (((PCONTROL)hParentWnd)->we_rdr) {
|
|
/** only get render from parent */
|
|
pNewCtrl->we_rdr = ((PCONTROL)hParentWnd)->we_rdr;
|
|
++pNewCtrl->we_rdr->refcount;
|
|
}
|
|
else
|
|
return HWND_INVALID;
|
|
}
|
|
else {
|
|
/** set window renderer */
|
|
set_control_renderer (pNewCtrl, werdr_name);
|
|
}
|
|
|
|
/** set window element data */
|
|
while (we_attrs && we_attrs->we_attr_id != -1) {
|
|
//__mg_append_window_element_data (pNewCtrl,
|
|
// we_attrs->we_attr_id, we_attrs->we_attr);
|
|
DWORD _old;
|
|
__mg_set_window_element_data ((HWND)pNewCtrl,
|
|
we_attrs->we_attr_id, we_attrs->we_attr, &_old);
|
|
++we_attrs;
|
|
}
|
|
|
|
/** prefer to parent font */
|
|
if (pNewCtrl->dwExStyle & WS_EX_USEPARENTFONT)
|
|
pNewCtrl->pLogFont = ((PCONTROL)hParentWnd)->pLogFont;
|
|
else
|
|
pNewCtrl->pLogFont = GetSystemFont (SYSLOGFONT_CONTROL);
|
|
|
|
/* reserve by humingming 2010.7.6 */
|
|
/*if (spCaption) {
|
|
int len = __mg_strlen (pNewCtrl->pLogFont, spCaption)+2;
|
|
|
|
pNewCtrl->spCaption = FixStrAlloc (len);
|
|
if (len > 0)
|
|
//strcpy (pNewCtrl->spCaption, spCaption);
|
|
memcpy (pNewCtrl->spCaption, spCaption, len);
|
|
}
|
|
else
|
|
pNewCtrl->spCaption = "";*/
|
|
|
|
pNewCtrl->children = NULL;
|
|
pNewCtrl->active = NULL;
|
|
pNewCtrl->old_under_pointer = NULL;
|
|
pNewCtrl->primitive = NULL;
|
|
|
|
pNewCtrl->notif_proc = NULL;
|
|
|
|
pNewCtrl->pMainWin = (PMAINWIN)pMainWin;
|
|
pNewCtrl->pParent = (PCONTROL)hParentWnd;
|
|
pNewCtrl->next = NULL;
|
|
|
|
pNewCtrl->pcci = cci;
|
|
|
|
if (dwExStyle & WS_EX_CTRLASMAINWIN) {
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
pNewCtrl->surf = GAL_CreateSurfaceForZNodeAs (pMainWin->surf,
|
|
pNewCtrl->right - pNewCtrl->left,
|
|
pNewCtrl->bottom - pNewCtrl->top);
|
|
#else
|
|
if (!(pNewCtrl->pGCRInfo = malloc (sizeof (GCRINFO)))) {
|
|
goto error;
|
|
}
|
|
#endif
|
|
}
|
|
else {
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
pNewCtrl->surf = pMainWin->surf;
|
|
#else
|
|
pNewCtrl->pGCRInfo = pMainWin->pGCRInfo;
|
|
#endif
|
|
pNewCtrl->idx_znode = pMainWin->idx_znode;
|
|
}
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
pNewCtrl->iBkColor = GAL_MapRGBA (pNewCtrl->surf->format,
|
|
GetRValue (cci->dwBkColor), GetGValue (cci->dwBkColor),
|
|
GetBValue (cci->dwBkColor), GetAValue (cci->dwBkColor));
|
|
#else
|
|
pNewCtrl->iBkColor = cci->iBkColor;
|
|
#endif
|
|
|
|
if (SendMessage (HWND_DESKTOP,
|
|
MSG_NEWCTRLINSTANCE,
|
|
(WPARAM)hParentWnd, (LPARAM)pNewCtrl) < 0)
|
|
goto error;
|
|
|
|
if (cci->dwStyle & CS_OWNDC)
|
|
pNewCtrl->dwExStyle |= WS_EX_USEPRIVATECDC;
|
|
|
|
if (pNewCtrl->dwExStyle & WS_EX_USEPRIVATECDC) {
|
|
if (pMainWin->dwExStyle & WS_EX_AUTOSECONDARYDC)
|
|
pNewCtrl->privCDC = GetSecondarySubDC (pMainWin->secondaryDC,
|
|
(HWND)pNewCtrl, TRUE);
|
|
else
|
|
pNewCtrl->privCDC = CreatePrivateClientDC ((HWND)pNewCtrl);
|
|
}
|
|
else
|
|
pNewCtrl->privCDC = 0;
|
|
|
|
|
|
if (SendMessage ((HWND)pNewCtrl, MSG_NCCREATE, 0, (LPARAM)dwAddData)) {
|
|
goto error;
|
|
}
|
|
|
|
if (SendMessage ((HWND)pNewCtrl, MSG_CREATE,
|
|
(WPARAM)hParentWnd, (LPARAM)dwAddData)) {
|
|
SendMessage (HWND_DESKTOP,
|
|
MSG_REMOVECTRLINSTANCE, (WPARAM)hParentWnd, (LPARAM)pNewCtrl);
|
|
goto error;
|
|
}
|
|
|
|
//set ctrl as main
|
|
if(pNewCtrl->dwExStyle & WS_EX_CTRLASMAINWIN){
|
|
pNewCtrl->next_ctrl_as_main = (PCONTROL)pNewCtrl->pMainWin->hFirstChildAsMainWin;
|
|
pMainWin->hFirstChildAsMainWin = (HWND) pNewCtrl;
|
|
}
|
|
|
|
SendMessage ((HWND)pNewCtrl, MSG_SIZECHANGING,
|
|
(WPARAM)&rcExpect, (LPARAM)&pNewCtrl->left);
|
|
|
|
SendMessage ((HWND)pNewCtrl, MSG_CHANGESIZE,
|
|
(WPARAM)(&pNewCtrl->left), 0);
|
|
|
|
/* houhh 20080820, not need to call UpdateWindow() here. */
|
|
if (pNewCtrl->pParent->dwStyle & WS_VISIBLE
|
|
&& pNewCtrl->dwStyle & WS_VISIBLE) {
|
|
#if 1
|
|
InvalidateRect ((HWND)pNewCtrl, NULL, TRUE);
|
|
SendAsyncMessage ((HWND)pNewCtrl, MSG_NCPAINT, 0, 0);
|
|
#else
|
|
UpdateWindow ((HWND)pNewCtrl, TRUE);
|
|
#endif
|
|
}
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
// Close file descriptor to free kernel memory?
|
|
if (dwExStyle & WS_EX_CTRLASMAINWIN && pNewCtrl->surf->shared_header) {
|
|
close (pNewCtrl->surf->shared_header->fd);
|
|
pNewCtrl->surf->shared_header->fd = -1;
|
|
}
|
|
#endif
|
|
|
|
return (HWND)pNewCtrl;
|
|
|
|
error:
|
|
if (dwExStyle & WS_EX_CTRLASMAINWIN) {
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
if (pNewCtrl->surf)
|
|
GAL_FreeSurface (pNewCtrl->surf);
|
|
#else
|
|
if (pNewCtrl->pGCRInfo)
|
|
free (pNewCtrl->pGCRInfo);
|
|
#endif
|
|
}
|
|
free (pNewCtrl);
|
|
|
|
return HWND_INVALID;
|
|
}
|
|
|
|
BOOL GUIAPI DestroyWindow (HWND hWnd)
|
|
{
|
|
//
|
|
PCONTROL pCtrl;
|
|
PCONTROL pParent;
|
|
|
|
if (!IsControl (hWnd)) return FALSE;
|
|
|
|
if (SendMessage (hWnd, MSG_DESTROY, 0, 0)) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* destroy all controls of this window */
|
|
DestroyAllControls (hWnd);
|
|
|
|
/* kill all timers of this window */
|
|
KillTimer (hWnd, 0);
|
|
|
|
pCtrl = (PCONTROL)hWnd;
|
|
pParent = pCtrl->pParent;
|
|
if (pParent->active == (PCONTROL) hWnd)
|
|
pParent->active = NULL;
|
|
if (pParent->old_under_pointer == (PCONTROL) hWnd)
|
|
pParent->old_under_pointer = NULL;
|
|
if (pParent->primitive == (PCONTROL) hWnd)
|
|
pParent->primitive = NULL;
|
|
|
|
if (SendMessage (HWND_DESKTOP,
|
|
MSG_REMOVECTRLINSTANCE, (WPARAM)pParent, (LPARAM)pCtrl))
|
|
{
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
__mg_reset_mainwin_capture_info (pCtrl);
|
|
|
|
pCtrl->dwStyle &= ~WS_VISIBLE;
|
|
if (IsWindowVisible ((HWND) pParent))
|
|
InvalidateRect ((HWND) pParent, (PRECT)(&pCtrl->left), TRUE);
|
|
|
|
if (pCtrl->privCDC) {
|
|
if (pCtrl->pMainWin->dwExStyle & WS_EX_AUTOSECONDARYDC) {
|
|
ReleaseSecondarySubDC (pCtrl->privCDC);
|
|
}
|
|
else {
|
|
if (pCtrl->pMainWin->secondaryDC)
|
|
ReleaseSecondarySubDC (pCtrl->privCDC);
|
|
else
|
|
DeletePrivateDC (pCtrl->privCDC);
|
|
}
|
|
pCtrl->privCDC = 0;
|
|
}
|
|
|
|
if (sg_repeat_msg.hwnd == hWnd)
|
|
sg_repeat_msg.hwnd = 0;
|
|
|
|
ThrowAwayMessages (hWnd);
|
|
|
|
if (pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN) {
|
|
PMAINWIN pMainWin;
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
EmptyClipRgn (&pCtrl->pGCRInfo->crgn);
|
|
#endif
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_destroy (&pCtrl->pGCRInfo->lock);
|
|
#endif
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
GAL_FreeSurface (pCtrl->surf);
|
|
#else
|
|
free (pCtrl->pGCRInfo);
|
|
#endif
|
|
|
|
pMainWin = pCtrl->pMainWin;
|
|
if ((PCONTROL) pMainWin->hFirstChildAsMainWin == pCtrl)
|
|
pMainWin->hFirstChildAsMainWin = (HWND)pCtrl->next_ctrl_as_main;
|
|
else {
|
|
PCONTROL tmp = (PCONTROL) pMainWin->hFirstChildAsMainWin;
|
|
BOOL found = FALSE;
|
|
|
|
while(tmp) {
|
|
if (tmp->next_ctrl_as_main == pCtrl) {
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
|
|
tmp = tmp->next_ctrl_as_main;
|
|
}
|
|
if (found)
|
|
tmp->next_ctrl_as_main = pCtrl->next_ctrl_as_main;
|
|
}
|
|
}
|
|
EmptyClipRgn (&pCtrl->InvRgn.rgn);
|
|
#ifdef _MGRM_THREADS
|
|
pthread_mutex_destroy (&pCtrl->InvRgn.lock);
|
|
#endif
|
|
|
|
if (pCtrl->spCaption)
|
|
FreeFixStr (pCtrl->spCaption);
|
|
|
|
__mg_free_window_element_data (hWnd);
|
|
--pCtrl->we_rdr->refcount;
|
|
|
|
free (pCtrl);
|
|
return TRUE;
|
|
}
|
|
|
|
NOTIFPROC GUIAPI SetNotificationCallback (HWND hwnd, NOTIFPROC notif_proc)
|
|
{
|
|
NOTIFPROC old_proc;
|
|
PCONTROL control = (PCONTROL)hwnd;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hwnd), NULL);
|
|
|
|
old_proc = control->notif_proc;
|
|
|
|
control->notif_proc = notif_proc;
|
|
|
|
return old_proc;
|
|
}
|
|
|
|
NOTIFPROC GUIAPI GetNotificationCallback (HWND hwnd)
|
|
{
|
|
PCONTROL control = (PCONTROL)hwnd;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hwnd), NULL);
|
|
|
|
return control->notif_proc;
|
|
}
|
|
|
|
/****************************** Hooks support ********************************/
|
|
#ifndef _MGRM_PROCESSES
|
|
MSGHOOK GUIAPI RegisterKeyMsgHook (void* context, MSGHOOK hook)
|
|
{
|
|
return (MSGHOOK)SendMessage (HWND_DESKTOP,
|
|
MSG_REGISTERKEYHOOK, (WPARAM)context, (LPARAM)hook);
|
|
}
|
|
|
|
MSGHOOK GUIAPI RegisterMouseMsgHook (void* context, MSGHOOK hook)
|
|
{
|
|
return (MSGHOOK)SendMessage (HWND_DESKTOP,
|
|
MSG_REGISTERMOUSEHOOK, (WPARAM)context, (LPARAM)hook);
|
|
}
|
|
|
|
#else
|
|
|
|
/*
|
|
* REQID_REGKEYHOOK 0x0016
|
|
*/
|
|
HWND GUIAPI RegisterKeyHookWindow (HWND hwnd, DWORD flag)
|
|
{
|
|
HWND old_hwnd = HWND_NULL;
|
|
|
|
if (!mgIsServer) {
|
|
|
|
REGHOOKINFO info;
|
|
REQUEST req;
|
|
|
|
info.id_op = ID_REG_KEY;
|
|
info.hwnd = hwnd;
|
|
info.flag = flag;
|
|
|
|
req.id = REQID_REGISTERHOOK;
|
|
req.data = &info;
|
|
req.len_data = sizeof (REGHOOKINFO);
|
|
ClientRequest (&req, &old_hwnd, sizeof (HWND));
|
|
}
|
|
|
|
return old_hwnd;
|
|
}
|
|
|
|
HWND GUIAPI RegisterMouseHookWindow (HWND hwnd, DWORD flag)
|
|
{
|
|
HWND old_hwnd = HWND_NULL;
|
|
if (!mgIsServer) {
|
|
|
|
REGHOOKINFO info;
|
|
REQUEST req;
|
|
|
|
info.id_op = ID_REG_MOUSE;
|
|
info.hwnd = hwnd;
|
|
info.flag = flag;
|
|
|
|
req.id = REQID_REGISTERHOOK;
|
|
req.data = &info;
|
|
req.len_data = sizeof (REGHOOKINFO);
|
|
ClientRequest (&req, &old_hwnd, sizeof (HWND));
|
|
}
|
|
|
|
return old_hwnd;
|
|
}
|
|
#endif
|
|
|
|
/**************************** IME support ************************************/
|
|
int GUIAPI RegisterIMEWindow (HWND hWnd)
|
|
{
|
|
#ifdef _MGRM_PROCESSES
|
|
if (mgIsServer) {
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), -1);
|
|
|
|
return SendMessage (HWND_DESKTOP, MSG_IME_REGISTER, (WPARAM)hWnd, 0);
|
|
}else
|
|
return ERR_INV_HWND;
|
|
#else
|
|
return SendMessage (HWND_DESKTOP, MSG_IME_REGISTER, (WPARAM)hWnd, 0);
|
|
#endif
|
|
}
|
|
|
|
int GUIAPI UnregisterIMEWindow (HWND hWnd)
|
|
{
|
|
#ifdef _MGRM_PROCESSES
|
|
if (mgIsServer) {
|
|
return SendMessage (HWND_DESKTOP, MSG_IME_UNREGISTER, (WPARAM)hWnd, 0);
|
|
}else
|
|
return ERR_IME_NOSUCHIMEWND;
|
|
#else
|
|
return SendMessage (HWND_DESKTOP, MSG_IME_UNREGISTER, (WPARAM)hWnd, 0);
|
|
#endif
|
|
}
|
|
|
|
int GUIAPI GetIMEStatus (int StatusCode)
|
|
{
|
|
#ifdef _MGRM_PROCESSES
|
|
if (!mgIsServer) {
|
|
REQUEST req;
|
|
int ret;
|
|
|
|
req.id = REQID_GETIMESTAT;
|
|
req.data = &StatusCode;
|
|
req.len_data = sizeof(int);
|
|
|
|
ClientRequest (&req, &ret, sizeof(int));
|
|
return ret;
|
|
} else
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_IME_GETSTATUS, (WPARAM)StatusCode, 0);
|
|
#else
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_IME_GETSTATUS, (WPARAM)StatusCode, 0);
|
|
#endif
|
|
}
|
|
|
|
int GUIAPI SetIMEStatus (int StatusCode, int Value)
|
|
{
|
|
#ifdef _MGRM_PROCESSES
|
|
if (!mgIsServer) {
|
|
REQUEST req;
|
|
unsigned int que_data;
|
|
int ret;
|
|
|
|
que_data = (StatusCode<<16)|Value;
|
|
|
|
req.id = REQID_SETIMESTAT;
|
|
req.data = &que_data;
|
|
req.len_data = sizeof(int);
|
|
|
|
ClientRequest (&req, &ret, sizeof(int));
|
|
return ret;
|
|
} else
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_IME_SETSTATUS, (WPARAM)StatusCode, Value);
|
|
#else
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_IME_SETSTATUS, (WPARAM)StatusCode, Value);
|
|
#endif
|
|
}
|
|
|
|
int GUIAPI SetIMETargetInfo (const IME_TARGET_INFO *info)
|
|
{
|
|
int ret = 0;
|
|
#ifdef _MGRM_PROCESSES
|
|
if (!mgIsServer) {
|
|
REQUEST req;
|
|
|
|
req.id = REQID_SETIMEPOS;
|
|
req.data = info;
|
|
req.len_data = sizeof(IME_TARGET_INFO);
|
|
|
|
ClientRequest (&req, &ret, sizeof(int));
|
|
return ret;
|
|
} else
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_IME_SET_TARGET_INFO, 0, (LPARAM)info);
|
|
#else
|
|
ret = SendMessage (HWND_DESKTOP,
|
|
MSG_IME_SET_TARGET_INFO, 0, (LPARAM)info);
|
|
return ret;
|
|
#endif
|
|
}
|
|
|
|
int GUIAPI GetIMEPos (POINT *pt)
|
|
{
|
|
IME_TARGET_INFO info;
|
|
int ret = GetIMETargetInfo (&info);
|
|
*pt = info.ptCaret;
|
|
return ret;
|
|
}
|
|
|
|
int GUIAPI SetIMEPos (const POINT* pt)
|
|
{
|
|
IME_TARGET_INFO info;
|
|
memset (&info, 0, sizeof(IME_TARGET_INFO));
|
|
info.ptCaret = *pt;
|
|
return SetIMETargetInfo (&info);
|
|
}
|
|
|
|
int GUIAPI GetIMETargetInfo (IME_TARGET_INFO *info)
|
|
{
|
|
#ifdef _MGRM_PROCESSES
|
|
if (!mgIsServer) {
|
|
REQUEST req;
|
|
|
|
req.id = REQID_GETIMEPOS;
|
|
req.data = 0;
|
|
req.len_data = 0;
|
|
|
|
return ClientRequest (&req, info, sizeof (IME_TARGET_INFO));
|
|
}
|
|
else {
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_IME_GET_TARGET_INFO, 0, (LPARAM)info);
|
|
}
|
|
#else
|
|
return SendMessage (HWND_DESKTOP,
|
|
MSG_IME_GET_TARGET_INFO, 0, (LPARAM)info);
|
|
#endif
|
|
}
|
|
|
|
HICON GetWindowIcon (HWND hWnd)
|
|
{
|
|
PMAINWIN pWin;
|
|
if (!(pWin = gui_CheckAndGetMainWindowPtr (hWnd)))
|
|
return 0;
|
|
|
|
return pWin->hIcon;
|
|
}
|
|
|
|
HICON SetWindowIcon (HWND hWnd, HICON hIcon, BOOL bRedraw)
|
|
{
|
|
PMAINWIN pWin;
|
|
HICON hOld;
|
|
|
|
if (!(pWin = gui_CheckAndGetMainWindowPtr (hWnd)))
|
|
return 0;
|
|
|
|
hOld = pWin->hIcon;
|
|
pWin->hIcon = hIcon;
|
|
|
|
if (bRedraw) { /* redraw the whole window */
|
|
UpdateWindow (hWnd, TRUE);
|
|
}
|
|
else { /* draw caption only */
|
|
HDC hdc;
|
|
const WINDOW_ELEMENT_RENDERER* rdr;
|
|
|
|
hdc = get_valid_dc (pWin, FALSE);
|
|
rdr = GetWindowInfo ((HWND)pWin)->we_rdr;
|
|
rdr ->draw_caption ((HWND)pWin, hdc,
|
|
!(pWin->dwStyle & WS_DISABLED) && (GetActiveWindow () == hWnd));
|
|
|
|
if (pWin->pMainWin->secondaryDC) {
|
|
draw_secondary_nc_area (pWin, rdr, hdc, HT_CAPTION);
|
|
}
|
|
release_valid_dc (pWin, hdc);
|
|
}
|
|
return hOld;
|
|
}
|
|
|
|
/**
|
|
* calc_xybanned_rects:
|
|
* this function calculates x-y-banned rectangles of MYBITMAP or BITMAP.
|
|
*
|
|
* param hwnd : the window handle
|
|
* param type : the type of mask: TYPE_MYBITMAP or TYPE_BITMAP
|
|
* param mask : MYBITMAP with 8 bits per pixels
|
|
* param nr_rcs(out) : number of the x-y-banned rectangles
|
|
*
|
|
* return : return NULL on failure, return the x-y-banned
|
|
* rectangles on success.
|
|
*
|
|
* note : You are responsible to free the x-y-banned rectangles.
|
|
*
|
|
* Author : NuohuaZhou
|
|
* Data : 2008-02-20
|
|
*/
|
|
|
|
#define XYBANNED_RECT_NR_INIT 10
|
|
#define XYBANNED_RECT_NR_INC 10
|
|
|
|
#define TYPE_MYBITMAP 1
|
|
#define TYPE_BITMAP 2
|
|
|
|
#include "../newgal/blit.h"
|
|
|
|
static RECT4MASK* calc_xybanned_rects (HDC hdc, int type, const void* mask,
|
|
int* nr_rcs)
|
|
{
|
|
Uint32 x, y;
|
|
Uint32 pixel;
|
|
POINT section;
|
|
RECT4MASK* xybanned_rects;
|
|
BOOL ismask, combined;
|
|
int max_index, max_calloced_nr;
|
|
int prev_pos_from, prev_pos_to, next_pos_from, next_pos_to;
|
|
int combined_index, i;
|
|
int w = 0, h = 0;
|
|
BYTE* bits = NULL;
|
|
Uint32 transparent = 0;
|
|
unsigned sA = 0;
|
|
unsigned sR, sG, sB;
|
|
|
|
if (!mask) return NULL;
|
|
|
|
if (type == TYPE_MYBITMAP) {
|
|
w = ((MYBITMAP*)mask)->w;
|
|
h = ((MYBITMAP*)mask)->h;
|
|
bits = ((MYBITMAP*)mask)->bits;
|
|
transparent = ((MYBITMAP*)mask)->transparent;
|
|
if (((MYBITMAP*)mask)->depth != 8) {
|
|
return NULL;
|
|
}
|
|
}
|
|
else {
|
|
w = ((BITMAP*)mask)->bmWidth;
|
|
h = ((BITMAP*)mask)->bmHeight;
|
|
bits = ((BITMAP*)mask)->bmBits;
|
|
if (!(dc_HDC2PDC(hdc))->surface->format) {
|
|
return NULL;
|
|
}
|
|
}
|
|
if (h <= 0) return NULL;
|
|
|
|
if (nr_rcs)
|
|
*nr_rcs = 0;
|
|
|
|
max_calloced_nr = XYBANNED_RECT_NR_INIT;
|
|
xybanned_rects = (RECT4MASK *) calloc (max_calloced_nr, sizeof (RECT4MASK));
|
|
if (!xybanned_rects) {
|
|
return NULL;
|
|
}
|
|
|
|
max_index = 0;
|
|
next_pos_from = 0;
|
|
next_pos_to = max_index;
|
|
|
|
for (y = 0; y < h; y++) {
|
|
section.x = 0;
|
|
section.y = 0;
|
|
ismask = FALSE;
|
|
combined = FALSE;
|
|
prev_pos_from = next_pos_from;
|
|
prev_pos_to = next_pos_to;
|
|
|
|
for (x = 0; x <= w; x++) {
|
|
if (type == TYPE_BITMAP) {
|
|
GAL_PixelFormat* pixfmt = (dc_HDC2PDC(hdc))->surface->format;
|
|
int bpp = ((BITMAP*)mask)->bmBytesPerPixel;
|
|
BYTE* p = bits + (y * ((BITMAP*)mask)->bmPitch) + x * bpp;
|
|
if (((BITMAP*)mask)->bmType & BMP_TYPE_ALPHA_MASK) {
|
|
BITMAP* bmp = (BITMAP*)mask;
|
|
int x = ((p - bmp->bmBits)%bmp->bmPitch);
|
|
int y = ((p - bmp->bmBits)/bmp->bmPitch);
|
|
int pitch = bmp->bmAlphaPitch;
|
|
sA = bmp->bmAlphaMask[y * pitch + x/bmp->bmBytesPerPixel];
|
|
DISEMBLE_RGB (p, bpp, pixfmt, pixel, sR, sG, sB);
|
|
}
|
|
else {
|
|
DISEMBLE_RGBA (p, bpp, pixfmt, pixel, sR, sG, sB, sA);
|
|
}
|
|
sR ^= sG & sB; /* prevent unused-but-set-variable warning */
|
|
}
|
|
else {
|
|
pixel = bits [y * ((MYBITMAP*)mask)->pitch + x];
|
|
}
|
|
|
|
if ((type == TYPE_MYBITMAP && pixel != transparent)
|
|
|| (type == TYPE_BITMAP && sA != 0))
|
|
{
|
|
if (!ismask) {
|
|
section.x = x;
|
|
ismask = TRUE;
|
|
}
|
|
}
|
|
|
|
if (((type == TYPE_MYBITMAP && pixel == transparent)
|
|
|| (type == TYPE_BITMAP && sA == 0)
|
|
|| x == w) && ismask) {
|
|
ismask = FALSE;
|
|
section.y = x;
|
|
combined_index = -1;
|
|
if (prev_pos_from <= max_index && prev_pos_to <= max_index) {
|
|
for (i = prev_pos_from; i <= prev_pos_to; ++i) {
|
|
if (y == xybanned_rects[i].bottom
|
|
&& section.x == xybanned_rects[i].left
|
|
&& section.y == xybanned_rects[i].right) {
|
|
++xybanned_rects[i].bottom;
|
|
combined_index = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (-1 == combined_index) {
|
|
++ max_index;
|
|
if (max_index >= max_calloced_nr) {
|
|
max_calloced_nr += XYBANNED_RECT_NR_INC;
|
|
xybanned_rects = (RECT4MASK *) realloc (xybanned_rects,
|
|
max_calloced_nr * sizeof (RECT4MASK));
|
|
if (!xybanned_rects) {
|
|
return NULL;
|
|
}
|
|
}
|
|
xybanned_rects[max_index].left = section.x;
|
|
xybanned_rects[max_index].top = y;
|
|
xybanned_rects[max_index].right = section.y;
|
|
xybanned_rects[max_index].bottom = y + 1;
|
|
} else {
|
|
if (!combined) {
|
|
combined = TRUE;
|
|
next_pos_from = combined_index;
|
|
} else {
|
|
if (combined_index < next_pos_from)
|
|
next_pos_from = combined_index;
|
|
}
|
|
}
|
|
}
|
|
}// for (x = 0; x < w; ++x)
|
|
|
|
if ((section.y == 0) && (section.x == 0)) {
|
|
next_pos_to = next_pos_from = max_index + 1;
|
|
} else {
|
|
next_pos_to = max_index;
|
|
}
|
|
}// for (y = 1; y < h; ++y)
|
|
|
|
if (nr_rcs)
|
|
*nr_rcs = max_index + 1;
|
|
|
|
return xybanned_rects;
|
|
}
|
|
|
|
/* Internal functions for non-rectangle window. */
|
|
static int set_window_mask_rect (HWND hWnd, WINMASKINFO* mask_info)
|
|
{
|
|
MASKRECT *new_maskrect;
|
|
PCONTROL pCtrl;
|
|
int i, retval;
|
|
|
|
if (!mask_info->rcs)
|
|
return FALSE;
|
|
|
|
if (IsControl (hWnd)) {
|
|
/*
|
|
* Because control without WS_EX_CTRLASMAINWIN has not
|
|
* the own Z order node, we should allocate memory for an
|
|
* array of mask_info->nr_rcs for mask_rects.
|
|
*
|
|
* The prev of first mask_rects indicates the number of the array.
|
|
* The next of last mask_rects is 0.
|
|
* The other prev and next of mask_rects is the index of the array.
|
|
*/
|
|
pCtrl = (PCONTROL) hWnd;
|
|
|
|
if (!(pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN)) {
|
|
|
|
if (pCtrl->mask_rects == NULL) {
|
|
pCtrl->mask_rects =
|
|
(MASKRECT *) calloc (mask_info->nr_rcs, sizeof (MASKRECT));
|
|
|
|
if (!pCtrl->mask_rects) {
|
|
_WRN_PRINTF ("No enough memory!\n");
|
|
free (mask_info->rcs);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
/*
|
|
* when number of calloced mask_rects is not enough,
|
|
* free the old memory and calloc more.
|
|
*/
|
|
if (pCtrl->mask_rects->prev < mask_info->nr_rcs) {
|
|
|
|
new_maskrect =
|
|
(MASKRECT *) calloc (mask_info->nr_rcs, sizeof (MASKRECT));
|
|
if (!new_maskrect) {
|
|
_WRN_PRINTF ("No enough memory!\n");
|
|
free (mask_info->rcs);
|
|
return FALSE;
|
|
}
|
|
free (pCtrl->mask_rects);
|
|
pCtrl->mask_rects = new_maskrect;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < mask_info->nr_rcs; ++i) {
|
|
(pCtrl->mask_rects + i)->left = mask_info->rcs[i].left;
|
|
(pCtrl->mask_rects + i)->top = mask_info->rcs[i].top;
|
|
(pCtrl->mask_rects + i)->right = mask_info->rcs[i].right;
|
|
(pCtrl->mask_rects + i)->bottom = mask_info->rcs[i].bottom;
|
|
(pCtrl->mask_rects + i)->prev = i;
|
|
(pCtrl->mask_rects + i)->next = i + 1;
|
|
}
|
|
|
|
/** the field [prev] is used to store number of mask_rects */
|
|
pCtrl->mask_rects->prev = mask_info->nr_rcs;
|
|
|
|
/** mark the end with 0 */
|
|
(pCtrl->mask_rects + mask_info->nr_rcs - 1)->next = 0;
|
|
|
|
free (mask_info->rcs);
|
|
|
|
if (pCtrl->dwStyle & WS_VISIBLE) {
|
|
ShowWindow (hWnd, SW_HIDE);
|
|
ShowWindow (hWnd, SW_SHOW);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/* Since 4.2.0: use MSG_SETWINDOWMASK messasge instead of
|
|
__kernel_change_z_node_mask_rect */
|
|
retval = (int)SendMessage (HWND_DESKTOP,
|
|
MSG_SETWINDOWMASK, (WPARAM)hWnd, (LPARAM)mask_info);
|
|
// retval = __kernel_change_z_node_mask_rect (hWnd, mask_info->rcs, mask_info->nr_rcs);
|
|
free (mask_info->rcs);
|
|
|
|
/* Since 4.2.0. Under compositing schema, the compositor should refresh
|
|
the screen for the change of region. */
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
pCtrl = (PCONTROL)hWnd;
|
|
|
|
if (!retval && pCtrl->dwStyle & WS_VISIBLE) {
|
|
MoveWindow (hWnd, pCtrl->left, pCtrl->top,
|
|
pCtrl->right - pCtrl->left - 1,
|
|
pCtrl->bottom - pCtrl->top - 1, FALSE);
|
|
MoveWindow (hWnd, pCtrl->left, pCtrl->top,
|
|
pCtrl->right - pCtrl->left + 1,
|
|
pCtrl->bottom - pCtrl->top + 1, FALSE);
|
|
}
|
|
#endif
|
|
|
|
return retval;
|
|
}
|
|
|
|
BOOL GUIAPI SetWindowMask (HWND hWnd, const MYBITMAP* mask)
|
|
{
|
|
WINMASKINFO mask_info;
|
|
int retval;
|
|
|
|
mask_info.rcs = calc_xybanned_rects (HDC_SCREEN, TYPE_MYBITMAP, mask,
|
|
&mask_info.nr_rcs);
|
|
if (!mask_info.rcs)
|
|
return FALSE;
|
|
|
|
retval = set_window_mask_rect (hWnd, &mask_info);
|
|
return (retval == 0 ? TRUE : FALSE);
|
|
}
|
|
|
|
BOOL GUIAPI SetWindowMaskEx (HWND hWnd, HDC hdc, const BITMAP* mask)
|
|
{
|
|
WINMASKINFO mask_info;
|
|
int retval;
|
|
|
|
mask_info.rcs = calc_xybanned_rects (hdc, TYPE_BITMAP, mask,
|
|
&mask_info.nr_rcs);
|
|
if (!mask_info.rcs)
|
|
return FALSE;
|
|
|
|
retval = set_window_mask_rect (hWnd, &mask_info);
|
|
return (retval == 0 ? TRUE : FALSE);
|
|
}
|
|
|
|
BOOL GUIAPI SetWindowRegion (HWND hWnd, const CLIPRGN * region)
|
|
{
|
|
MASKRECT *new_maskrect;
|
|
PCLIPRECT cliprc;
|
|
WINMASKINFO mask_info;
|
|
PCONTROL pCtrl;
|
|
int retval, nr_rcs, i;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
|
|
if (!region || IsEmptyClipRgn(region))
|
|
return FALSE;
|
|
|
|
/** number of rect */
|
|
for (nr_rcs = 1, cliprc = region->head;
|
|
cliprc && cliprc != region->tail; nr_rcs++, cliprc=cliprc->next);
|
|
|
|
if (IsControl (hWnd)) {
|
|
/*
|
|
* Because control without WS_EX_CTRLASMAINWIN has not
|
|
* the Z order node, we should allocate memory for an
|
|
* array of nr_rcs for mask_rects.
|
|
*
|
|
* The prev of first mask_rects indicates the number of the array.
|
|
* The next of last mask_rects is 0.
|
|
* The other prev and next of mask_rects is the index of the array.
|
|
*/
|
|
pCtrl = (PCONTROL) hWnd;
|
|
|
|
if (!(pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN)) {
|
|
|
|
if (pCtrl->mask_rects == NULL) {
|
|
pCtrl->mask_rects =
|
|
(MASKRECT *) calloc (nr_rcs, sizeof (MASKRECT));
|
|
|
|
if (!pCtrl->mask_rects) {
|
|
_WRN_PRINTF ("No enough memory!\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
/*
|
|
* when number of calloced mask_rects is not enough,
|
|
* free the old memory and calloc more.
|
|
*/
|
|
if (pCtrl->mask_rects->prev < nr_rcs) {
|
|
new_maskrect =
|
|
(MASKRECT *) calloc (nr_rcs, sizeof (MASKRECT));
|
|
|
|
if (!new_maskrect) {
|
|
_WRN_PRINTF ("No enough memory!\n");
|
|
return FALSE;
|
|
}
|
|
free (pCtrl->mask_rects);
|
|
pCtrl->mask_rects = new_maskrect;
|
|
}
|
|
}
|
|
|
|
cliprc = region->head;
|
|
|
|
for (i = 0; i < nr_rcs; ++i) {
|
|
(pCtrl->mask_rects + i)->left = cliprc->rc.left;
|
|
(pCtrl->mask_rects + i)->top = cliprc->rc.top;
|
|
(pCtrl->mask_rects + i)->right = cliprc->rc.right;
|
|
(pCtrl->mask_rects + i)->bottom = cliprc->rc.bottom;
|
|
(pCtrl->mask_rects + i)->prev = i;
|
|
(pCtrl->mask_rects + i)->next = i + 1;
|
|
cliprc = cliprc->next;
|
|
}
|
|
|
|
/** the field [prev] is used to store number of mask_rects */
|
|
pCtrl->mask_rects->prev = nr_rcs;
|
|
|
|
/** mark the end with 0 */
|
|
(pCtrl->mask_rects + nr_rcs - 1)->next = 0;
|
|
|
|
if (pCtrl->dwStyle & WS_VISIBLE) {
|
|
ShowWindow (hWnd, SW_HIDE);
|
|
ShowWindow (hWnd, SW_SHOW);
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
mask_info.nr_rcs = nr_rcs;
|
|
mask_info.rcs = (RECT4MASK *) calloc (nr_rcs, sizeof(RECT4MASK));
|
|
if (mask_info.rcs == NULL) {
|
|
_WRN_PRINTF ("No enough memory!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
cliprc = region->head;
|
|
for (i = 0; i < nr_rcs; ++i) {
|
|
mask_info.rcs[i].left = cliprc->rc.left;
|
|
mask_info.rcs[i].top = cliprc->rc.top;
|
|
mask_info.rcs[i].right = cliprc->rc.right;
|
|
mask_info.rcs[i].bottom = cliprc->rc.bottom;
|
|
cliprc = cliprc->next;
|
|
}
|
|
|
|
retval = (int)SendMessage (HWND_DESKTOP,
|
|
MSG_SETWINDOWMASK, (WPARAM)hWnd, (LPARAM)&mask_info);
|
|
// XXX: retval = __kernel_change_z_node_mask_rect (hWnd, rect, nr_rcs);
|
|
free (mask_info.rcs);
|
|
|
|
/* Since 4.2.0. Under compositing schema, the compositor should refresh
|
|
the screen for the change of region. */
|
|
#ifndef _MGSCHEMA_COMPOSITING
|
|
pCtrl = (PCONTROL)hWnd;
|
|
|
|
if (!retval && pCtrl->dwStyle & WS_VISIBLE) {
|
|
MoveWindow (hWnd, pCtrl->left, pCtrl->top,
|
|
pCtrl->right - pCtrl->left - 1,
|
|
pCtrl->bottom - pCtrl->top - 1, FALSE);
|
|
MoveWindow (hWnd, pCtrl->left, pCtrl->top,
|
|
pCtrl->right - pCtrl->left + 1,
|
|
pCtrl->bottom - pCtrl->top + 1, FALSE);
|
|
}
|
|
#endif
|
|
|
|
return (retval == 0 ? TRUE : FALSE);
|
|
}
|
|
|
|
BOOL GUIAPI GetWindowRegion (HWND hWnd, CLIPRGN* region)
|
|
{
|
|
PCONTROL pCtrl;
|
|
int nr_rects, i;
|
|
RECT rc;
|
|
|
|
MG_CHECK_RET (MG_IS_NORMAL_WINDOW(hWnd), FALSE);
|
|
MG_CHECK_RET (region != NULL, FALSE);
|
|
|
|
pCtrl = (PCONTROL) hWnd;
|
|
if (IsControl (hWnd) && !(pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN)) {
|
|
/* the field [prev] is used to store number of mask_rects */
|
|
nr_rects = pCtrl->mask_rects->prev;
|
|
if (nr_rects == 0) {
|
|
GetWindowRect (hWnd, &rc);
|
|
OffsetRect (&rc, rc.left, rc.top);
|
|
return SetClipRgn (region, &rc);
|
|
}
|
|
else {
|
|
EmptyClipRgn (region);
|
|
for (i = 0; i < nr_rects; i++) {
|
|
rc.left = (pCtrl->mask_rects + i)->left;
|
|
rc.top = (pCtrl->mask_rects + i)->top;
|
|
rc.right = (pCtrl->mask_rects + i)->right;
|
|
rc.bottom = (pCtrl->mask_rects + i)->bottom;
|
|
if (!AddClipRect (region, &rc))
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
return __kernel_get_window_region (hWnd, region) > 0;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef __TARGET_MSTUDIO__
|
|
|
|
int GUIAPI GetWindowZOrder(HWND hWnd)
|
|
{
|
|
PCONTROL pCtrl, pCtrlTmp;
|
|
int idx;
|
|
if(!IsWindow(hWnd))
|
|
return -1;
|
|
|
|
if(IsMainWindow(hWnd))
|
|
return 0;
|
|
|
|
pCtrl = (PCONTROL)hWnd;
|
|
|
|
pCtrlTmp = pCtrl->pParent->children;
|
|
|
|
idx = 0;
|
|
while(pCtrlTmp && pCtrl != pCtrlTmp)
|
|
{
|
|
idx ++;
|
|
pCtrlTmp = pCtrlTmp->next;
|
|
}
|
|
|
|
return idx;
|
|
}
|
|
|
|
int GUIAPI SetWindowZOrder (HWND hWnd, int zorder)
|
|
{
|
|
int idx;
|
|
PCONTROL pCtrl, pCtrlTmp;
|
|
if (!IsWindow(hWnd))
|
|
return -1;
|
|
|
|
if (IsMainWindow(hWnd))
|
|
return 0;
|
|
|
|
pCtrl = (PCONTROL)hWnd;
|
|
|
|
pCtrlTmp = pCtrl->pParent->children;
|
|
|
|
idx = 0;
|
|
while (idx < zorder && pCtrlTmp && pCtrlTmp != pCtrl) {
|
|
idx ++;
|
|
pCtrlTmp = pCtrlTmp->next;
|
|
}
|
|
|
|
if (idx < zorder) {
|
|
// Move Down
|
|
pCtrlTmp = pCtrlTmp->next;
|
|
if (pCtrlTmp && pCtrl == pCtrl->pParent->children)
|
|
pCtrl->pParent->children = pCtrl->next;
|
|
while (idx < zorder && pCtrlTmp) {
|
|
//switch pCtrl and pCtrlTmp
|
|
pCtrl->next = pCtrlTmp->next;
|
|
pCtrlTmp->prev = pCtrl->prev;
|
|
pCtrl->prev = pCtrlTmp;
|
|
pCtrlTmp->next = pCtrl;
|
|
|
|
if (pCtrl->next)
|
|
pCtrl->next->prev = pCtrl;
|
|
if (pCtrlTmp->prev)
|
|
pCtrlTmp->prev->next = pCtrlTmp;
|
|
|
|
pCtrlTmp = pCtrl->next;
|
|
}
|
|
}
|
|
else if(pCtrlTmp && pCtrlTmp != pCtrl) {
|
|
// Move Up
|
|
PCONTROL prev;
|
|
do {
|
|
prev = pCtrl->prev;
|
|
if (prev == NULL)
|
|
break;
|
|
prev->next = pCtrl->next;
|
|
pCtrl->prev = prev->prev;
|
|
pCtrl->next = prev;
|
|
prev->prev = pCtrl;
|
|
if (pCtrl->prev)
|
|
pCtrl->prev->next = pCtrl;
|
|
if (prev->next)
|
|
prev->next->prev = prev;
|
|
} while (prev != pCtrlTmp);
|
|
|
|
if (pCtrlTmp == pCtrl->pParent->children)
|
|
pCtrl->pParent->children = pCtrl;
|
|
|
|
if (prev == NULL)
|
|
return 0;
|
|
}
|
|
|
|
return idx;
|
|
}
|
|
|
|
#endif /* defined __TARGET_MSTUDIO__ */
|
|
|
|
/* Since 4.2.0 */
|
|
BOOL GUIAPI SetMainWindowAlwaysTop (HWND hMainWnd, BOOL fSet)
|
|
{
|
|
PMAINWIN pMainWin;
|
|
|
|
if (hMainWnd == HWND_DESKTOP || hMainWnd == 0) {
|
|
return FALSE;
|
|
}
|
|
else if (!(pMainWin = gui_CheckAndGetMainWindowPtr (hMainWnd))) {
|
|
return FALSE;
|
|
}
|
|
|
|
return (BOOL)SendMessage (HWND_DESKTOP,
|
|
MSG_SETALWAYSTOP, (WPARAM)pMainWin, (LPARAM)fSet);
|
|
}
|
|
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
BOOL GUIAPI SetMainWindowCompositing (HWND hMainWnd, int type, DWORD arg)
|
|
{
|
|
PMAINWIN pMainWin;
|
|
COMPOSITINGINFO info;
|
|
|
|
if (hMainWnd == HWND_DESKTOP || hMainWnd == 0) {
|
|
return FALSE;
|
|
}
|
|
else if (!(pMainWin = gui_CheckAndGetMainWindowPtr (hMainWnd))) {
|
|
return FALSE;
|
|
}
|
|
|
|
info.type = type;
|
|
info.arg = arg;
|
|
return (BOOL)SendMessage (HWND_DESKTOP,
|
|
MSG_SETCOMPOSITING, (WPARAM)pMainWin, (LPARAM)&info);
|
|
}
|
|
#endif /* defined _MGSCHEMA_COMPOSITING */
|
|
|