#include "win32\win32guts.h"
#include <commdlg.h>
#ifndef _APRICOT_H_
#include "apricot.h"
#endif
#include "guts.h"
#include "File.h"
#include "Menu.h"
#include "Image.h"
#include "Region.h"
#include "Window.h"
#include "Application.h"
#ifdef __cplusplus
extern "C" {
#endif
#define sys (( PDrawableData)(( PComponent) self)-> sysData)->
#define dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
#define var (( PWidget) self)->
#define HANDLE sys handle
#define DHANDLE(x) dsys(x) handle
#define GET_REGION(obj) (&(dsys(obj)s.region))
#define WinShowWindow(WND) SetWindowPos( WND, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW|SWP_NOACTIVATE);
#define WinHideWindow(WND) SetWindowPos( WND, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_HIDEWINDOW);
#define apc_widget_redraw(self) apc_widget_invalidate_rect(self,NULL)
void
process_transparents( Handle self)
{
int i;
RECT mr;
objCheck;
GetWindowRect(( HWND) var handle, &mr);
for ( i = 0; i < var widgets. count; i++) {
HWND xwnd;
Handle x = var widgets. items[ i];
dobjCheck(x);
xwnd = DHANDLE(x);
if ( dsys(x) options. aptTransparent && IsWindowVisible( xwnd)) {
RECT r, dr;
GetWindowRect( xwnd, &r);
IntersectRect( &dr, &r, &mr);
if ( !IsRectEmpty( &dr))
InvalidateRect( xwnd, NULL, false);
}
}
}
typedef struct _ViewProfile {
ColorSet colors;
Point pos;
Point size;
Point virtSize;
Bool enabled;
Bool visible;
Bool focused;
Handle capture;
HRGN shape;
} ViewProfile, *PViewProfile;
static void
get_view_ex( Handle self, PViewProfile p)
{
int i;
if ( !p) return;
p-> capture = apc_widget_is_captured( self);
for ( i = 0; i <= ciMaxId; i++) p-> colors[ i] = apc_widget_get_color( self, i);
if ( sys className == WC_FRAME) {
p-> pos = apc_window_get_client_pos( self);
p-> size = apc_window_get_client_size( self);
} else {
p-> pos = apc_widget_get_pos( self);
p-> size = apc_widget_get_size( self);
}
p-> virtSize = var virtualSize;
p-> enabled = apc_widget_is_enabled( self);
p-> focused = apc_widget_is_focused( self);
p-> visible = apc_widget_is_visible( self);
p-> shape = CreateRectRgn(0,0,0,0);
if ( sys className == WC_FRAME && is_apt(aptLayered))
i = GetWindowRgn((HWND) var handle, p->shape);
else
i = GetWindowRgn( HANDLE, p->shape);
if (!i) {
DeleteObject(p->shape);
p->shape = NULL;
}
}
static void
set_view_ex( Handle self, PViewProfile p)
{
int i;
Bool clip_by_children;
if ( sys className == WC_FRAME && is_apt(aptLayered)) {
SetWindowRgn((HWND) var handle, p-> shape, true);
} else
SetWindowRgn( HANDLE, p-> shape, true);
apc_widget_set_visible( self, false);
for ( i = 0; i <= ciMaxId; i++) apc_widget_set_color( self, p-> colors[i], i);
apc_widget_set_font( self, &var font);
if ( sys className == WC_FRAME) {
apc_window_set_client_rect( self, p-> pos. x, p-> pos. y, p-> size.x, p-> size.y);
} else {
apc_widget_set_rect( self, p-> pos. x, p-> pos. y, p-> size.x, p-> size.y);
}
var virtualSize = p-> virtSize;
apc_widget_set_enabled( self, p-> enabled);
if ( p-> focused) apc_widget_set_focused( self);
clip_by_children = is_apt(aptClipByChildren);
apt_set(aptClipByChildren); /* by default widget created with clipping */
apc_widget_set_clip_by_children(self, clip_by_children);
apc_widget_set_visible( self, p-> visible);
if ( p-> capture) apc_widget_set_capture( self, 1, NULL_HANDLE);
if ( !InvalidateRect(( HWND) var handle, NULL, false)) apiErr;
process_transparents( self);
}
static Bool repost_msgs( PostMsg * msg, Handle self)
{
PostMessage(( HWND) var handle, WM_POSTAL, ( WPARAM) self, ( LPARAM) msg);
return false;
}
static Bool
create_group( Handle self, Handle owner, Bool syncPaint, Bool clipOwner,
Bool taskListed, int className, DWORD style, DWORD exstyle,
Bool usePos, Bool useSize,
ViewProfile * vprf, HWND parentHandle)
{
HWND ret = NULL;
HWND old = HANDLE;
HWND old2 = (HWND) var handle;
HWND behind = HWND_TOP;
HWND ownerView = ( HWND) (( PWidget) owner)-> handle;
HWND parentView = (( PDrawableData)(( PComponent) owner)-> sysData)-> parent;
int count = 0;
Bool reset = false;
Handle * list = NULL;
const WCHAR wnull = 0;
if ( HANDLE)
{
int i;
if (( DHANDLE( owner) == sys owner) && ( clipOwner == is_apt( aptClipOwner)))
{
behind = GetWindow( HANDLE, GW_HWNDPREV);
if ( behind == NULL) behind = HWND_TOP;
}
var stage = csAxEvents;
if ( kind_of( self, CWidget))
{
PWidget g = ( PWidget) self;
list = g-> widgets. items;
count = g-> widgets. count;
}
var self-> end_paint_info( self);
var self-> end_paint( self);
reset = true;
for( i = 0; i < count; i++)
get_view_ex( list[ i], ( ViewProfile*)( dsys( list[ i]) recreateData = malloc( sizeof( ViewProfile))));
}
switch (( int) className)
{
case WC_FRAME:
{
HWND frame;
RECT r;
int rcp[4] = {0,0,0,0};
Bool layered = is_apt(aptLayered);
if ( !clipOwner) parentView = HWND_DESKTOP;
if ( !taskListed && ( parentView == HWND_DESKTOP || parentView == NULL))
parentView = DHANDLE( application);
if ( !usePos) rcp[0] = rcp[1] = CW_USEDEFAULT;
if ( !useSize) rcp[2] = rcp[3] = CW_USEDEFAULT;
if ( !( frame = CreateWindowExW( exstyle, layered ? L"LayeredFrame" : L"GenericFrame", &wnull,
style | WS_CLIPCHILDREN,
rcp[0], rcp[1], rcp[2], rcp[3],
parentView, NULL, guts. instance, NULL)))
apiErrRet;
if ( !SetWindowPos( frame, behind, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE))
apiErr;
if ((( PApplication) application)-> topExclModal &&
((( PApplication) application)-> topExclModal != self)
)
if ( !SetWindowPos( frame, DHANDLE((( PApplication) application)-> topExclModal),
0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE))
apiErr;
GetClientRect( frame, &r);
if ( old2 )
SetWindowLongPtr( old2, GWLP_USERDATA, 0);
if ( old )
SetWindowLongPtr( old, GWLP_USERDATA, 0);
if ( layered ) {
if ( !( ret = CreateWindowExW( WS_EX_LAYERED|WS_EX_TOOLWINDOW, L"Generic", &wnull,
WS_VISIBLE | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
r. left, r. top, r. right, r. bottom, NULL, NULL,
guts. instance, NULL)))
apiErr;
} else {
if ( !( ret = CreateWindowExW( 0, L"Generic", &wnull,
WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, r. right - r. left, r. bottom - r. top, frame, NULL,
guts. instance, NULL)))
apiErr;
}
sys lastSize. x = r. right - r. left;
sys yOverride = sys lastSize. y = r. bottom - r. top;
sys handle = frame;
SetWindowLongPtr( frame, GWLP_USERDATA, ( LONG) self);
}
break;
case WC_CUSTOM:
if ( !parentHandle && ( !clipOwner || owner == application)) {
style &= ~WS_CHILD;
style |= WS_POPUP;
exstyle |= WS_EX_TOOLWINDOW;
}
if ( parentHandle) parentView = parentHandle;
sys parentHandle = parentHandle;
if ( old )
SetWindowLongPtr( old, GWLP_USERDATA, 0);
if ( !( ret = CreateWindowExW( exstyle, L"Generic", &wnull,
style | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 0, 0,
parentView, NULL, guts. instance, NULL)))
apiErrRet;
if ( !SetWindowPos( ret, behind, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE))
apiErr;
sys handle = ret;
break;
}
apt_assign( aptClipOwner, clipOwner);
apt_assign( aptSyncPaint, syncPaint);
apt_set( aptEnabled);
apt_clear( aptRepaintPending );
apt_clear( aptMovePending );
sys className = className;
sys parent = ret;
var handle = ( Handle) ret;
sys owner = ownerView;
if ( !reset)
sys pointer = LoadCursor( guts. instance, IDC_ARROW);
SetWindowLongPtr( ret, GWLP_USERDATA, ( LONG) self);
if ( reset)
{
int i;
Handle oldOwner = var owner; var owner = owner;
if ( sys className == WC_FRAME) {
apc_window_set_client_rect( self, vprf-> pos. x, vprf-> pos. y, vprf-> size. x, vprf-> size. y);
} else {
apc_widget_set_rect( self, vprf-> pos. x, vprf-> pos. y, vprf-> size. x, vprf-> size. y);
}
var owner = oldOwner;
for ( i = 0; i < count; i++) ((( PComponent) list[ i])-> self)-> recreate( list[ i]);
if ( sys className == WC_FRAME)
{
SetMenu( HANDLE, GetMenu( old));
SetMenu( old, NULL);
}
if ( old2 != old ) {
if ( !DestroyWindow( old2 ))
apiErr;
}
if ( !DestroyWindow( old))
apiErr;
if ( var postList) list_first_that( var postList, repost_msgs, ( void*)self);
}
PostMessage( ret, WM_PRIMA_CREATE, 0, 0);
if ( !reset) {
/* set manually cmMove and cmSize when windows are configured automatically */
if ( !usePos) {
Event e;
Point sz = apc_window_get_client_pos( self);
memset( &e, 0, sizeof(e));
e. gen. source = self;
e. cmd = cmMove;
e. gen. P. x = sz. x;
e. gen. P. y = sz. y;
CComponent(self)->message( self, &e);
if ( PObject( self)-> stage == csDead) return false;
}
if ( !useSize) {
Event e;
Point sz = apc_window_get_client_size( self);
memset( &e, 0, sizeof(e));
e. gen. source = self;
e. cmd = cmSize;
e. gen. P. x = e. gen. R. right = sz. x;
e. gen. P. y = e. gen. R. top = sz. y;
CComponent(self)->message( self, &e);
if ( PObject( self)-> stage == csDead) return false;
}
}
return true;
}
static void
notify_sys_handle( Handle self )
{
Event ev = {cmSysHandle};
objCheck;
ev. gen. source = self;
var self-> message( self, &ev);
}
// Window
Bool
apc_window_create( Handle self, Handle owner, Bool syncPaint, int borderIcons,
int borderStyle, Bool taskList, int windowState,
int on_top, Bool usePos, Bool useSize, Bool layered)
{
Bool reset = false;
ViewProfile vprf;
int oStage = var stage;
WCHAR * saved_caption = NULL;
WindowData ws;
HICON icon = (HICON) NULL_HANDLE;
WINDOWPLACEMENT wp = {sizeof(WINDOWPLACEMENT)};
DWORD style = WS_CLIPCHILDREN | WS_OVERLAPPED
| (( borderIcons & biSystemMenu) ? WS_SYSMENU : 0)
| (( borderIcons & biMinimize) ? WS_MINIMIZEBOX : 0)
| (( borderIcons & biMaximize) ? WS_MAXIMIZEBOX : 0)
| (( borderIcons & biTitleBar) ? 0 : WS_POPUP)
| (( borderStyle == bsSizeable) ? WS_THICKFRAME : 0)
| (( borderStyle == bsSingle ) ? WS_BORDER : 0)
| (( borderStyle == bsDialog ) ? WS_BORDER : 0)
| (( windowState == wsMinimized) ? WS_MINIMIZE : 0)
| (( windowState == wsMaximized) ? WS_MAXIMIZE : 0)
;
DWORD exstyle = 0
| (( borderStyle == bsDialog ) ? WS_EX_DLGMODALFRAME : 0)
;
objCheck false;
dobjCheck( owner) false;
if ( guts. displayBMInfo. bmiHeader. biBitCount <= 8) layered = false;
if ( !kind_of( self, CWidget)) apcErrRet( errInvObject);
apcErrClear;
if (( var handle != NULL_HANDLE) && (
( DHANDLE( owner) != sys owner)
|| ( borderStyle != sys s. window. borderStyle)
|| ( borderIcons != sys s. window. borderIcons)
|| ( taskList != is_apt( aptTaskList))
|| ( layered != is_apt( aptLayered))
))
{
int len = GetWindowTextLengthW( HANDLE ) + 1;
if (( saved_caption = (WCHAR*) malloc( sizeof(WCHAR) * len)) != NULL )
GetWindowTextW( HANDLE, saved_caption, len );
// Windows 8 shell is observed to send WM_SIZE(0,0) on ShowWindow(SW_SHOWNORMAL)
// when application started with /min flag
apt_set( aptIgnoreSizeMessages );
apc_window_set_window_state( self, windowState);
apt_clear( aptIgnoreSizeMessages );
// prevent cmSize/cmWindowStage message loss if recreate goes with WS_XXX change.
if ( sys recreateData) {
memcpy( &vprf, sys recreateData, sizeof( vprf));
free( sys recreateData);
sys recreateData = NULL;
} else
get_view_ex( self, &vprf);
ws = sys s. window;
if ( !GetWindowPlacement( HANDLE, &wp)) apiErr;
if ( wp. showCmd == SW_SHOWMINIMIZED && windowState != wsMinimized )
wp. showCmd = ( windowState == wsMaximized ) ? SW_SHOWMAXIMIZED : SW_NORMAL;
usePos = useSize = 1; // prevent using shell-position flags for recreate
icon = ( HICON) SendMessage( HANDLE, WM_GETICON, ICON_BIG, 0);
reset = true;
}
HWND_lock( true);
if ( !reset) apt_set( aptClipByChildren );
apt_assign( aptLayeredRequested, layered );
apt_assign( aptLayered, layered );
if ( reset || ( var handle == NULL_HANDLE))
if ( !create_group( self, owner, syncPaint, false,
taskList, WC_FRAME, style, exstyle, usePos, useSize, &vprf, NULL)) {
if ( on_top >= 0) {
apt_assign( aptOnTop, on_top);
if ( on_top > 0)
SetWindowPos( sys handle, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
HWND_lock( false);
if ( saved_caption ) free( saved_caption );
return false;
}
ws. borderStyle = sys s. window. borderStyle = borderStyle;
ws. borderIcons = sys s. window. borderIcons = borderIcons;
ws. state = sys s. window. state = windowState;
apt_assign( aptSyncPaint, syncPaint);
apt_assign( aptTaskList, taskList);
if ( usePos) apt_set( aptWinPosDetermined);
if ( reset)
{
Handle oldOwner = var owner;
var owner = owner;
apc_window_set_window_state( self, windowState);
var owner = oldOwner;
set_view_ex( self, &vprf);
sys s. window = ws;
if ( windowState != wsMaximized)
GetWindowRect( HANDLE, &wp. rcNormalPosition);
if ( !SetWindowPlacement( HANDLE, &wp)) apiErr;
var stage = oStage;
if ( icon) SendMessage( HANDLE, WM_SETICON, ICON_BIG, ( LPARAM) icon);
}
else {
guts. topWindows++;
}
if ( on_top >= 0) {
apt_assign( aptOnTop, on_top);
if ( on_top > 0)
SetWindowPos( sys handle, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
SetWindowTextW( HANDLE, saved_caption );
if ( saved_caption ) free( saved_caption );
HWND_lock( false);
if ( reset ) {
notify_sys_handle( self );
if ( layered ) hwnd_repaint_layered(self, false);
}
return guts.apcError == 0;
}
Bool
apc_window_activate( Handle self)
{
if ( self) {
HWND w;
objCheck false;
w = HANDLE;
SetForegroundWindow( w);
SetActiveWindow( w);
return true;
}
return false;
}
Bool
apc_window_is_active( Handle self)
{
return apc_window_get_active() == self;
}
Handle
apc_window_get_active( void)
{
Handle self = hwnd_to_view( GetActiveWindow());
if ( !self)
return NULL_HANDLE;
if ( sys className == WC_FRAME)
return self;
else if ( !is_apt( aptClipOwner)) {
return hwnd_top_level( self);
} else
return NULL_HANDLE;
}
Bool
apc_window_close( Handle self)
{
objCheck true;
if ( !PostMessage( HANDLE, WM_CLOSE, 0, 0)) apiErrRet;
return true;
}
int
apc_window_get_border_icons( Handle self)
{
objCheck 0;
return sys s. window. borderIcons;
}
int
apc_window_get_border_style( Handle self)
{
objCheck 0;
return sys s. window. borderStyle;
}
ApiHandle
apc_window_get_client_handle( Handle self)
{
objCheck 0;
return ( ApiHandle) var handle;
}
Point
apc_window_get_client_pos( Handle self)
{
Point delta = get_window_borders( sys s. window. borderStyle);
Handle parent = var self-> get_parent( self);
Point p = {0,0}, sz = CWidget( parent)-> get_size( parent);
RECT r;
objCheck p;
if ( apc_window_get_window_state( self) == wsMinimized) {
WINDOWPLACEMENT w = { sizeof( WINDOWPLACEMENT)};
if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
p. x = w. rcNormalPosition. left + delta. x;
p. y = sz. y - w. rcNormalPosition. bottom + delta. y;
} else {
GetWindowRect( HANDLE, &r);
p. x = r. left + delta. x;
p. y = sz. y - r. bottom + delta. y;
}
return p;
}
Point
apc_window_get_client_size( Handle self)
{
RECT r;
Point p = { 0,0};
objCheck p;
if ( apc_window_get_window_state( self) == wsMinimized) {
// cannot acquire client extension at this time. Using euristic calculations.
WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
Point delta = get_window_borders( sys s. window. borderStyle);
int menuY = (( PWindow) self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0;
int titleY = ( sys s. window. borderIcons & biTitleBar) ?
GetSystemMetrics( SM_CYCAPTION) : 0;
if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
p. x = w. rcNormalPosition. right - w. rcNormalPosition. left - delta. x * 2;
p. y = w. rcNormalPosition. bottom - w. rcNormalPosition. top - delta. y * 2
- menuY - titleY;
} else {
GetWindowRect(( HWND) var handle, &r);
p. x = r. right - r. left;
p. y = r. bottom - r. top;
}
return p;
}
Bool
apc_window_get_icon( Handle self, Handle icon)
{
HICON p;
HCURSOR save;
Bool ret;
objCheck false;
p = ( HICON) SendMessage( HANDLE, WM_GETICON, ICON_BIG, 0);
if ( icon == NULL_HANDLE) return p != NULL;
save = sys pointer;
sys pointer = p;
ret = apc_pointer_get_bitmap( self, icon);
sys pointer = save;
return ret;
}
int
apc_window_get_window_state( Handle self)
{
WINDOWPLACEMENT s = {sizeof( WINDOWPLACEMENT)};
objCheck wsNormal;
if ( !GetWindowPlacement( HANDLE, &s)) apiErr;
if ( s. showCmd == SW_SHOWMAXIMIZED) return wsMaximized;
if ( s. showCmd == SW_SHOWMINIMIZED) return wsMinimized;
return wsNormal;
}
Bool
apc_window_get_task_listed( Handle self)
{
objCheck false;
return is_apt( aptTaskList);
}
Bool
apc_window_get_on_top( Handle self)
{
objCheck false;
return is_apt( aptOnTop);
}
Bool
apc_window_set_caption( Handle self, const char * caption, Bool utf8)
{
objCheck false;
if ( utf8) {
WCHAR * c = alloc_utf8_to_wchar( caption, -1, NULL);
if ( !( rc = SetWindowTextW( HANDLE, c))) apiErr;
free( c);
} else {
if ( !( rc = SetWindowTextA( HANDLE, caption))) apiErr;
}
return rc == 0;
}
Bool
apc_window_set_client_pos( Handle self, int x, int y)
{
Point delta = get_window_borders( sys s. window. borderStyle);
RECT r;
Handle parent = var self-> get_parent( self);
Point sz = CWidget( parent)-> get_size( parent);
objCheck false;
if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);
apt_set( aptWinPosDetermined);
if ( var stage == csConstructing && apc_window_get_window_state( self) != wsNormal) {
WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
w. rcNormalPosition. top += sz. y - y + delta. y - w. rcNormalPosition. bottom;
w. rcNormalPosition. bottom = sz. y - y + delta. y;
w. rcNormalPosition. right += x - delta. x - w. rcNormalPosition. left;
w. rcNormalPosition. left = x - delta. x;
w. flags = 0;
if ( !SetWindowPlacement( HANDLE, &w)) apiErr;
} else {
if ( !GetWindowRect( HANDLE, &r)) apiErr;
x -= delta. x;
y = sz. y - ( r. bottom - r. top) - y + delta. y;
SetWindowPos( HANDLE, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
return true;
}
Bool
apc_window_set_client_size( Handle self, int x, int y)
{
RECT r, c, c2;
HWND h;
int ws = apc_window_get_window_state( self);
objCheck false;
if ( !hwnd_check_limits( x, y, false)) apcErrRet( errInvParams);
h = HANDLE;
if (( var stage == csConstructing && ws != wsNormal) || ws == wsMinimized) {
WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
Point delta = get_window_borders( sys s. window. borderStyle);
var virtualSize. x = x;
var virtualSize. y = y;
if ( x < 0) x = 0;
if ( y < 0) y = 0;
if ( !GetWindowPlacement( h, &w)) apiErr;
if ( !GetWindowRect( h, &c2)) apiErr;
if ( ws == wsMaximized) {
if ( !GetClientRect( h, &c)) apiErr;
}
else {
// cannot acquire client extension at this time. Using euristic calculations.
int menuY = (( PWindow) self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0;
int titleY = ( sys s. window. borderIcons & biTitleBar) ?
GetSystemMetrics( SM_CYCAPTION) : 0;
c = c2;
c. right -= delta. x * 2;
c. bottom -= delta. y * 2 + menuY + titleY;
}
w. rcNormalPosition. top = w. rcNormalPosition. bottom - y - ( c2. bottom - c2. top - c. bottom + c. top);
w. rcNormalPosition. right = x + ( c2. right - c2. left - c. right + c. left) + w. rcNormalPosition. left;
w. flags = 0;
if ( !SetWindowPlacement( h, &w)) apiErr;
} else {
if ( !GetWindowRect( h, &r)) apiErr;
if ( !GetClientRect( h, &c)) apiErr;
sys sizeLockLevel++;
var virtualSize. x = x;
var virtualSize. y = y;
if ( x < 0) x = 0;
if ( y < 0) y = 0;
SetWindowPos( h, 0,
r. left,
r. top - y + ( c. bottom - c. top),
x + r. right - r. left - c. right + c. left,
y + r. bottom - r. top - c. bottom + c. top,
SWP_NOZORDER | SWP_NOACTIVATE |
( is_apt( aptWinPosDetermined) ? 0 : SWP_NOMOVE)
);
sys sizeLockLevel--;
}
return true;
}
Bool
apc_window_set_client_rect( Handle self, int x, int y, int width, int height)
{
RECT r, c, c2;
HWND h;
int ws = apc_window_get_window_state( self);
Point delta = get_window_borders( sys s. window. borderStyle);
Handle parent = var self-> get_parent( self);
Point sz = CWidget( parent)-> get_size( parent);
objCheck false;
if ( !hwnd_check_limits( x, y, false)) apcErrRet( errInvParams);
if ( !hwnd_check_limits( width, height, false)) apcErrRet( errInvParams);
apt_set( aptWinPosDetermined);
h = HANDLE;
if (( var stage == csConstructing && ws != wsNormal) || ws == wsMinimized) {
WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
Point delta = get_window_borders( sys s. window. borderStyle);
var virtualSize. x = width;
var virtualSize. y = height;
if ( width < 0) width = 0;
if ( height < 0) height = 0;
if ( !GetWindowPlacement( h, &w)) apiErr;
if ( !GetWindowRect( h, &c2)) apiErr;
if ( ws == wsMaximized) {
if ( !GetClientRect( h, &c)) apiErr;
}
else {
// cannot acquire client extension at this time. Using euristic calculations.
int menuY = (( PWindow) self)-> menu ? GetSystemMetrics( SM_CYMENU) : 0;
int titleY = ( sys s. window. borderIcons & biTitleBar) ?
GetSystemMetrics( SM_CYCAPTION) : 0;
c = c2;
c. right -= delta. x * 2;
c. bottom -= delta. y * 2 + menuY + titleY;
}
w. rcNormalPosition. bottom = sz. y - y + delta. y;
w. rcNormalPosition. left = x - delta. x;
w. rcNormalPosition. top = w. rcNormalPosition. bottom - height - ( c2. bottom - c2. top - c. bottom + c. top);
w. rcNormalPosition. right = width + ( c2. right - c2. left - c. right + c. left) + w. rcNormalPosition. left;
w. flags = 0;
if ( !SetWindowPlacement( h, &w)) apiErr;
} else {
if ( !GetWindowRect( h, &r)) apiErr;
if ( !GetClientRect( h, &c)) apiErr;
sys sizeLockLevel++;
x -= delta. x;
y = sz. y - y - height - ( r. bottom - r. top - c. bottom + c. top) + delta. y;
var virtualSize. x = width;
var virtualSize. y = height;
if ( width < 0) width = 0;
if ( height < 0) height = 0;
SetWindowPos( h, 0,
x, y,
width + r. right - r. left - c. right + c. left,
height + r. bottom - r. top - c. bottom + c. top,
SWP_NOZORDER | SWP_NOACTIVATE);
sys sizeLockLevel--;
}
return true;
}
Bool
apc_window_set_menu( Handle self, Handle menu)
{
Point size;
objCheck false;
apcErrClear;
size = var self-> get_size( self);
SetMenu( HANDLE, menu ? ( HMENU) (( PComponent) menu)-> handle : NULL);
DrawMenuBar( HANDLE);
if ( apc_window_get_window_state( self) == wsNormal)
var self-> set_size( self, size);
return guts.apcError == 0;
}
Bool
apc_window_set_effects( Handle self, HV * effects )
{
return false;
}
Bool
apc_window_set_icon( Handle self, Handle icon)
{
HICON i;
objCheck false;
i = icon ? image_make_icon_handle( icon, guts. iconSizeLarge, NULL) : NULL;
i = ( HICON) SendMessage( HANDLE, WM_SETICON, ICON_BIG, ( LPARAM) i);
if ( i) DestroyIcon( i);
return true;
}
Bool
apc_window_set_window_state( Handle self, int state)
{
int fl = -1;
objCheck false;
switch ( state)
{
case wsMaximized: fl = SW_SHOWMAXIMIZED; break;
case wsMinimized: fl = SW_MINIMIZE; break;
case wsNormal : fl = SW_SHOWNORMAL; break;
}
if ( fl > 0)
{
ShowWindow( HANDLE, fl);
sys s. window. state = state;
}
return true;
}
static Bool
window_start_modal( Handle self, Bool shared, Handle insertBefore)
{
HWND wnd;
HWND active = GetActiveWindow();
objCheck false;
wnd = HANDLE;
if ( sys className != WC_FRAME) { apcErr( errInvParams); return false; }
sys s. window. oldFoc = apc_widget_get_focused();
if ( sys s. window. oldFoc) protect_object( sys s. window. oldFoc);
sys s. window. oldActive = active;
// setting window up
guts. focSysDisabled = 1;
CWindow( self)-> exec_enter_proc( self, shared, insertBefore);
apc_widget_set_enabled( self, 1);
SetWindowPos( wnd, 0, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW);
if ( sys s. window. state == wsMinimized)
ShowWindow( wnd, SW_RESTORE);
if ( !insertBefore) {
SetActiveWindow( wnd);
SetForegroundWindow( wnd);
} else {
HWND zorder;
dobjCheck( insertBefore) false;
zorder = GetWindow( DHANDLE( insertBefore), GW_HWNDNEXT);
if ( !zorder) zorder = HWND_BOTTOM;
SetWindowPos( wnd, zorder, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
if ( active)
SetActiveWindow( active);
}
objCheck false;
PostMessage( wnd, WM_DLGENTERMODAL, 1, 0);
guts. focSysDisabled = 0;
return true;
}
Bool
apc_window_execute( Handle self, Handle insertBefore)
{
objCheck false;
if ( !window_start_modal( self, false, insertBefore))
return false;
// message loop
{
MSG msg;
while ( GetMessage( &msg, NULL, 0, 0)) {
if ( !process_msg( &msg)) {
if ( !appDead)
PostThreadMessage( guts. mainThreadId, WM_TERMINATE, 0, 0);
break;
}
if ( self && !(( PWindow) self)-> modal)
break;
}
}
// !!note - at this point object may be unaccessible (except var area only).
return true;
}
Bool
apc_window_execute_shared( Handle self, Handle insertBefore)
{
objCheck false;
return window_start_modal( self, true, insertBefore);
}
Bool
apc_window_end_modal( Handle self)
{
HWND wnd;
objCheck false;
wnd = HANDLE;
guts. focSysDisabled = 1;
CWindow( self)-> exec_leave_proc( self);
WinHideWindow( wnd);
objCheck false;
apc_widget_set_enabled( self, 0);
objCheck false;
if ( application) {
Handle who = Application_popup_modal( application);
if ( sys s. window. oldActive)
SetActiveWindow( sys s. window. oldActive);
if ( !who && var owner)
CWidget( var owner)-> set_selected( var owner, 1);
if (( who = sys s. window. oldFoc)) {
if ( PWidget( who)-> stage == csNormal)
CWidget( who)-> set_focused( who, 1);
unprotect_object( who);
}
}
guts. focSysDisabled = 0;
return true;
}
// View management
Bool
apc_widget_map_points( Handle self, Bool toScreen, int count, Point * p)
{
int i;
Point sz = ((( PWidget) self)-> self)-> get_size( self);
Point appSz = apc_application_get_size( application);
if ( self == application)
return true;
objCheck false;
if ( toScreen) {
for ( i = 0; i < count; i++)
p[i]. y = sz. y - p[i]. y;
MapWindowPoints(( HWND) var handle, NULL, ( POINT * ) p, count);
for ( i = 0; i < count; i++)
p[i]. y = appSz. y - p[i].y;
} else {
for ( i = 0; i < count; i++)
p[i]. y = appSz. y - p[i]. y;
MapWindowPoints( NULL, ( HWND) var handle, ( POINT * ) p, count);
for ( i = 0; i < count; i++)
p[i]. y = sz. y - p[i]. y;
}
return true;
}
Color
apc_widget_map_color( Handle self, Color color)
{
if ((( color & clSysFlag) != 0) && (( color & wcMask) == 0)) color |= var widgetClass;
return remap_color( remap_color( color, true), false);
}
Bool
apc_widget_create( Handle self, Handle owner, Bool syncPaint, Bool clipOwner,
Bool transparent, ApiHandle parentHandle, Bool layered)
{
Bool reset = false, redraw = false;
ViewProfile vprf;
int oStage = var stage;
int exstyle;
objCheck false;
dobjCheck( owner) false;
if ( !kind_of( self, CWidget)) apcErr( errInvObject);
apcErrClear;
if ( parentHandle && !IsWindow(( HWND) parentHandle))
return false;
exstyle = 0;
if ( guts. displayBMInfo. bmiHeader. biBitCount <= 8) layered = false;
redraw = is_apt( aptLayeredRequested ) != layered;
apt_assign( aptLayeredRequested, layered );
apt_clear( aptLayered );
if ( layered && (( owner == application || !clipOwner ))) {
apt_set( aptLayered );
exstyle |= WS_EX_LAYERED;
}
if (( var handle != NULL_HANDLE) &&
(( DHANDLE( owner) != sys owner) ||
(( HWND) parentHandle != sys parentHandle) ||
( clipOwner != is_apt( aptClipOwner))
))
{
if ( sys recreateData) {
memcpy( &vprf, sys recreateData, sizeof( vprf));
free( sys recreateData);
sys recreateData = NULL;
} else
get_view_ex( self, &vprf);
reset = true;
}
if ( !reset) apt_set( aptClipByChildren );
if ( reset || ( var handle == NULL_HANDLE))
create_group( self, owner, syncPaint, clipOwner, 0, WC_CUSTOM,
WS_CHILD, exstyle, 1, 1, &vprf, ( HWND) parentHandle);
apt_set( aptWinPosDetermined);
if ( reset)
{
Handle oldOwner = var owner; var owner = owner;
set_view_ex( self, &vprf);
var owner = oldOwner;
var stage = oStage;
}
if ( is_apt( aptTransparent) != transparent && !reset)
redraw = true;
if ( redraw) apc_widget_redraw( self);
apt_assign( aptTransparent, transparent);
if ( reset) {
notify_sys_handle( self );
apc_widget_redraw( self);
}
return guts.apcError == 0;
}
Bool
apc_widget_begin_paint( Handle self, Bool insideOnPaint)
{
Bool useRPDraw = false;
objCheck false;
apcErrClear;
if ( is_apt( aptLayeredPaint )) {
sys transform2 = sys layeredPaintOffset;
} else if ( is_apt( aptTransparent)) {
if ( IsWindowVisible(( HWND) var handle)) {
HWND parent = GetParent( HANDLE);
if ( !parent) {
MSG msg;
list_add( &guts. transp, self);
WinHideWindow(( HWND) var handle);
if ( parent) apcUpdateWindow( parent);
while ( PeekMessage( &msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE)) {
DispatchMessage(&msg);
exception_check_raise();
}
if ( !parent) Sleep( 1);
WinShowWindow(( HWND) var handle);
apcUpdateWindow(( HWND) var handle);
list_delete( &guts. transp, self);
} else
useRPDraw = true;
}
sys transform2. x = 0;
sys transform2. y = 0;
} else {
sys transform2. x = 0;
sys transform2. y = 0;
}
apt_set( aptWinPS);
apt_set( aptCompatiblePS);
apt_assign( aptWM_PAINT, insideOnPaint);
if ( is_apt( aptLayeredPaint )) {
sys ps = sys layeredPaintSurface;
} else if ( is_apt( aptLayered )) {
RECT r;
insideOnPaint = false;
GetWindowRect( HANDLE, &r);
sys ps2 = GetDC(NULL);
sys ps = CreateCompatibleDC(sys ps2);
sys bm = CreateCompatibleBitmap(sys ps2, r. right - r. left, r. bottom - r. top);
sys stockBM = SelectObject(sys ps, sys bm);
} else if ( insideOnPaint) {
if ( !( sys ps = BeginPaint(( HWND) var handle, &sys paintStruc))) apiErrRet;
} else {
if ( !( sys ps = GetDC(( HWND) var handle))) apiErrRet;
}
if ( !is_apt(aptLayeredPaint) && is_opt( optBuffered) && insideOnPaint) {
RECT r;
HBITMAP bm;
HDC dc;
GetClipBox( sys ps, &r);
var w = r. right - r. left;
var h = r. bottom - r. top;
if ( var w == 0 || var h == 0) {
if ( !EndPaint(( HWND) var handle, &sys paintStruc)) apiErr;
apt_clear( aptWinPS);
apt_clear( aptWM_PAINT);
apt_clear( aptCompatiblePS);
sys ps = NULL;
return false;
}
if ( !( dc = CreateCompatibleDC( sys ps))) apiErr;
if ( sys pal) {
sys stockPalette = SelectPalette( dc, sys pal, 1);
RealizePalette( dc);
sys pal2 = SelectPalette( sys ps, sys pal, 1);
RealizePalette( sys ps);
}
if ( guts. displayBMInfo. bmiHeader. biBitCount == 8)
apt_clear( aptCompatiblePS);
bm = CreateCompatibleBitmap( sys ps, var w, var h);
if ( bm) {
sys ps2 = sys ps;
sys ps = dc;
sys stockBM = SelectObject( dc, bm);
sys bm = bm;
SetBrushOrgEx( dc, -r. left, -r. top, NULL);
apc_gp_set_transform( self, -r. left, -r. top);
sys transform2. x = r. left;
sys transform2. y = r. top;
apt_set( aptBitmap);
} else
apiErr;
} else if ( !is_apt(aptLayered) && !is_apt(aptLayeredPaint)) {
if ( sys pal) {
sys stockPalette = SelectPalette( sys ps, sys pal, 1);
RealizePalette( sys ps);
}
}
if ( useRPDraw) {
HDC dc;
Handle owner = var owner;
Point tr = dsys(owner)transform2;
Point ed = apc_widget_get_pos( self);
Point sz = apc_widget_get_size( self);
Point so = CWidget(owner)-> get_size( owner);
Bool flag;
int saved_dc_state;
POINT brushorg;
FLOAT miter;
CWidget( owner)-> begin_paint( owner);
dc = dsys( owner) ps;
dsys( owner) ps = sys ps;
dsys(owner) transform2. x += ed. x;
dsys(owner) transform2. y += so. y - sz. y - ed. y;
apc_gp_set_transform( owner, 0, 0);
apc_gp_set_text_out_baseline( owner, dsys(owner) options. aptTextOutBaseline);
saved_dc_state = SaveDC( sys ps );
SelectObject( sys ps, GetCurrentObject( dc, OBJ_PEN));
SelectObject( sys ps, GetCurrentObject( dc, OBJ_BRUSH));
SelectObject( sys ps, GetCurrentObject( dc, OBJ_FONT));
SelectObject( sys ps, GetCurrentObject( dc, OBJ_PAL));
SelectObject( sys ps, GetCurrentObject( dc, OBJ_EXTPEN));
SetTextAlign( sys ps, GetTextAlign( dc ));
GetBrushOrgEx( dc, &brushorg);
SetBrushOrgEx( sys ps, brushorg.x, brushorg.y, NULL);
GetMiterLimit( dc, &miter);
SetMiterLimit( sys ps, miter, NULL);
SetBkMode( sys ps, GetBkMode( dc ));
SetROP2( sys ps, GetROP2( dc ));
SetStretchBltMode( sys ps, GetStretchBltMode( dc ));
flag = exception_block(true);
CWidget( owner)-> notify( owner, "sH", "Paint", owner);
exception_block(flag);
RestoreDC( sys ps, saved_dc_state);
dsys(owner)transform2 = tr;
apc_gp_set_transform( owner, 0, 0);
dsys( owner) ps = dc;
CWidget( owner)-> end_paint( owner);
}
hwnd_enter_paint( self);
if ( useRPDraw) {
apc_gp_set_transform( self, sys transform. x, sys transform. y);
}
if ( is_apt(aptLayeredPaint)) {
Rect r;
r. left = 0;
r. bottom = 0;
r. right = sys lastSize. x - 1;
r. top = sys lastSize. y - 1;
apc_gp_set_clip_rect(self, r);
}
return true;
}
Bool
apc_widget_begin_paint_info( Handle self)
{
HRGN rgn;
objCheck false;
apt_set( aptWinPS);
apt_set( aptCompatiblePS);
sys transform2. x = 0;
sys transform2. y = 0;
if ( !( sys ps = GetDC(( HWND) var handle))) apiErrRet;
hwnd_enter_paint( self);
rgn = CreateRectRgn( 0, 0, 0, 0);
SelectClipRgn( sys ps, rgn);
DeleteObject( rgn);
return true;
}
Bool
apc_widget_destroy( Handle self)
{
objCheck false;
SetWindowLongPtr( HANDLE, GWLP_USERDATA, 0);
if ( sys pointer2) {
if ( sys pointer2 == sys pointer) SetCursor( NULL); // un-use resource first
if ( !DestroyCursor( sys pointer2)) apiErr;
}
if ( sys recreateData) free( sys recreateData);
if ( self == lastMouseOver) lastMouseOver = NULL_HANDLE;
if ( self == guts.dragTarget) guts.dragTarget = NULL_HANDLE;
if ( var handle == NULL_HANDLE) return true;
if ( sys className == WC_FRAME)
guts. topWindows--;
if ( !DestroyWindow( HANDLE)) apiErrRet;
return true;
}
PFont
apc_widget_default_font( PFont copyTo)
{
*copyTo = guts. windowFont;
copyTo-> pitch = fpDefault;
return copyTo;
}
static void
subpaint_layered_widgets( HWND self, HDC ps, HDC alpha_dc, POINT screen_offset, HRGN parent_shape)
{
HWND child = GetTopWindow( self );
if ( child ) child = GetWindow( child, GW_HWNDLAST );
while ( child != NULL ) {
Handle h;
RECT r;
HRGN shape;
Event ev;
POINT child_offset, size;
h = hwnd_to_view(child);
if ( h == NULL_HANDLE || !IsWindowVisible(child) || !dsys(h) options. aptClipOwner) {
child = GetWindow( child, GW_HWNDPREV);
continue;
}
GetWindowRect( child, &r);
r. left -= screen_offset. x;
r. top -= screen_offset. y;
r. right -= screen_offset. x;
r. bottom -= screen_offset. y;
size. x = r.right - r. left;
size. y = r.bottom - r. top;
child_offset. x = r. left;
child_offset. y = r. top;
dsys(h) options. aptLayeredPaint = 1;
dsys(h) layeredPaintOffset. x = -r. left;
dsys(h) layeredPaintOffset. y = -r. top;
dsys(h) layeredPaintSurface = ps;
shape = CreateRectRgn(0,0,0,0);
if ( GetWindowRgn( child, shape)) {
HRGN rect = CreateRectRgn( 0, 0, size.x, size.y);
CombineRgn( shape, shape, rect, RGN_AND);
DeleteObject( rect );
} else {
DeleteObject( shape );
shape = CreateRectRgn( 0, 0, size.x, size.y);
}
OffsetRgn( shape, child_offset. x, child_offset. y);
if ( parent_shape ) CombineRgn( shape, shape, parent_shape, RGN_AND );
dsys(h) layeredParentRegion = shape;
ev. cmd = cmPaint;
CWidget(h)-> message( h, &ev);
if ( !dsys(h) options. aptLayeredRequested) {
/* assigning opaque alpha over the child rect so Windows passes mouse events in */
StretchBlt( ps, r.left, r.top, size.x, size.y, alpha_dc, 0, 0, 1, 1, SRCPAINT);
}
dsys(h) options. aptLayeredPaint = 0;
subpaint_layered_widgets( child, ps, alpha_dc, screen_offset, shape);
DeleteObject( shape );
child = GetWindow( child, GW_HWNDPREV);
}
}
Bool
apc_widget_end_paint( Handle self)
{
objCheck false;
hwnd_leave_paint( self);
if ( is_apt( aptLayeredPaint )) {
// do nothing
} else if ( is_apt( aptLayered )) {
RECT r;
SIZE size;
POINT src, pos, *ppos = NULL;
BLENDFUNCTION bf;
HBITMAP alpha_bm, stock_alpha_bm;
HDC alpha_dc;
uint32_t * alpha_pixels;
GetWindowRect((HWND) var handle, &r);
if ( r. right - r. left <= 0 || r. bottom - r. top <= 0)
goto SKIP_ALPHA;
alpha_dc = CreateCompatibleDC( sys ps );
alpha_bm = image_create_argb_dib_section( alpha_dc, 1, 1, &alpha_pixels);
stock_alpha_bm = SelectObject( alpha_dc, alpha_bm);
*alpha_pixels = 0xFF000000;
/* subpaint children */
src. x = r. left;
src. y = r. top;
subpaint_layered_widgets((HWND) var handle, sys ps, alpha_dc, src, NULL);
SelectObject( alpha_dc, stock_alpha_bm);
DeleteObject( alpha_bm );
DeleteDC( alpha_dc );
size. cx = r. right - r. left;
size. cy = r. bottom - r. top;
src. x = 0;
src. y = 0;
bf. AlphaFormat = AC_SRC_ALPHA;
bf. SourceConstantAlpha = 255;
bf. BlendFlags = 0;
bf. BlendOp = AC_SRC_OVER;
if (is_apt(aptMovePending)) {
pos. x = sys layeredPos. x;
pos. y = sys layeredPos. y;
ppos = &pos;
apt_clear(aptMovePending);
}
if ( !UpdateLayeredWindow((HWND) var handle, NULL, ppos, &size, sys ps, &src, 0, &bf, ULW_ALPHA))
apiErr;
SKIP_ALPHA:
SelectObject(sys ps, sys stockBM);
DeleteObject(sys bm);
DeleteDC(sys ps);
ReleaseDC(( HWND) var handle, sys ps2);
sys ps = sys ps2 = NULL;
sys bm = sys stockBM = NULL;
} else if ( is_opt( optBuffered)) {
apt_clear( aptBitmap);
if ( sys bm != NULL) {
if ( !BitBlt( sys ps2, sys transform2. x, sys transform2. y, var w, var h, sys ps, 0, 0, SRCCOPY)) apiErr;
if ( sys stockBM)
SelectObject( sys ps, sys stockBM);
DeleteObject( sys bm);
}
if ( sys pal) {
SelectPalette( sys ps2, sys pal2, 1);
SelectPalette( sys ps, sys stockPalette, 1);
RealizePalette( sys ps2);
sys pal2 = NULL;
}
DeleteDC( sys ps);
sys ps = sys ps2;
sys bm = NULL;
sys ps2 = NULL;
sys stockBM = NULL;
}
if ( !is_apt(aptLayeredPaint) && sys ps != NULL) {
if ( is_apt( aptWinPS) && is_apt( aptWM_PAINT)) {
if ( !EndPaint(( HWND) var handle, &sys paintStruc)) apiErr;
} else if ( is_apt( aptWinPS))
if ( !ReleaseDC(( HWND) var handle, sys ps)) apiErr;
}
sys ps = NULL;
sys pal2 = NULL;
apt_clear( aptWinPS);
apt_clear( aptWM_PAINT);
apt_clear( aptCompatiblePS);
return true;
}
Bool
apc_widget_end_paint_info( Handle self)
{
Bool ok = true;
objCheck false;
hwnd_leave_paint( self);
if ( !( ok = ReleaseDC(( HWND) var handle, sys ps))) apiErr;
sys ps = NULL;
apt_clear( aptWinPS);
apt_clear( aptCompatiblePS);
return ok;
}
Bool
apc_widget_get_clip_by_children( Handle self)
{
objCheck false;
return is_apt(aptClipByChildren);
}
Bool
apc_widget_get_clip_owner( Handle self)
{
objCheck false;
return is_apt( aptClipOwner);
}
Color
apc_widget_get_color( Handle self, int index)
{
objCheck clInvalid;
return sys viewColors[ index];
}
Bool
apc_widget_get_first_click( Handle self)
{
objCheck false;
return is_apt( aptFirstClick);
}
Handle
apc_widget_get_focused()
{
return hwnd_to_view( GetFocus());
}
static PRECT map_Rect( Handle self, Rect * rect)
{
RECT __rectangle;
objCheck ( PRECT) rect;
GetWindowRect(( HWND) var handle, &__rectangle);
if ( is_apt( aptClipOwner) && ( var owner != application))
MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT) &__rectangle, 2);
rect-> bottom = ( __rectangle. bottom - __rectangle. top) - rect-> bottom;
rect-> top = ( __rectangle. bottom - __rectangle. top) - rect-> top;
// that is due the difference in field placement between Rect and RECT structures
if ( rect-> bottom > rect-> top) {
LONG i = rect-> bottom;
rect-> bottom = rect-> top;
rect-> top = i;
}
return ( PRECT) rect;
}
static Rect * map_RECT( Handle self, RECT * rect)
{
RECT __rectangle;
objCheck ( Rect*)rect;
GetWindowRect(( HWND) var handle, &__rectangle);
if ( is_apt( aptClipOwner) && ( var owner != application))
MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&__rectangle, 2);
rect-> bottom = ( __rectangle. bottom - __rectangle. top) - rect-> bottom;
rect-> top = ( __rectangle. bottom - __rectangle. top) - rect-> top;
// that is due the difference in field placement between Rect and RECT structures
if ( rect-> bottom < rect-> top) {
LONG i = rect-> bottom;
rect-> bottom = rect-> top;
rect-> top = i;
}
return ( Rect *) rect;
}
ApiHandle
apc_widget_get_handle( Handle self)
{
objCheck 0;
return ( ApiHandle) HANDLE;
}
ApiHandle
apc_widget_get_parent_handle( Handle self)
{
objCheck 0;
return ( ApiHandle) sys parentHandle;
}
Rect
apc_widget_get_invalid_rect( Handle self)
{
Rect r = {0,0,0,0};
objCheck r;
if ( GetUpdateRect(( HWND) var handle, ( PRECT) &r, false))
return *( map_RECT( self, ( PRECT) &r));
return r;
}
Bool
apc_widget_get_layered_request( Handle self)
{
return is_apt( aptLayeredRequested);
}
Bool
apc_widget_surface_is_layered( Handle self)
{
Handle top;
objCheck false;
if ( is_apt( aptLayered)) return true;
top = hwnd_layered_top_level(self);
if ( top && dsys(top) options. aptLayered ) return true;
return false;
}
Point
apc_widget_get_pos( Handle self)
{
RECT r;
Point p, sz = {0,0};
Handle parent;
objCheck sz;
parent = is_apt( aptClipOwner) ? var owner : application;
sz = ((( PWidget) parent)-> self)-> get_size( parent);
if ( sys className == WC_FRAME && apc_window_get_window_state( self) == wsMinimized) {
WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
p. x = w. rcNormalPosition. left;
p. y = sz. y - w. rcNormalPosition. bottom;
} else if ( is_apt( aptMovePending)) {
GetWindowRect( HANDLE, &r);
p. x = sys layeredPos. x;
p. y = sys layeredPos. y + r. bottom - r.top;
} else {
GetWindowRect( HANDLE, &r);
if ( is_apt( aptClipOwner) && ( var owner != application))
MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
p. x = r. left;
p. y = sz. y - r. bottom;
}
return p;
}
Point
apc_widget_get_size( Handle self)
{
RECT r;
Point p = {0,0};
objCheck p;
if ( sys className == WC_FRAME && apc_window_get_window_state( self) == wsMinimized) {
WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
if ( !GetWindowPlacement( HANDLE, &w)) apiErr;
p. x = w. rcNormalPosition. right - w. rcNormalPosition. left;
p. y = w. rcNormalPosition. bottom - w. rcNormalPosition. top;
} else {
GetWindowRect( HANDLE, &r);
if ( is_apt( aptClipOwner) && ( var owner != application))
MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
p. x = r. right - r. left;
p. y = r. bottom - r. top;
}
return p;
}
Handle
apc_widget_get_z_order( Handle self, int zOrderId)
{
Handle h;
HWND w;
UINT cmd1, cmd2;
objCheck NULL_HANDLE;
switch ( zOrderId) {
case zoFirst:
cmd1 = GW_HWNDFIRST;
cmd2 = GW_HWNDNEXT;
break;
case zoLast:
cmd1 = GW_HWNDLAST;
cmd2 = GW_HWNDPREV;
break;
case zoNext:
cmd1 = cmd2 = GW_HWNDNEXT;
break;
case zoPrev:
cmd1 = cmd2 = GW_HWNDPREV;
break;
default:
apcErr( errInvParams);
return NULL_HANDLE;
}
w = GetWindow( HANDLE, cmd1);
if ( !w) return NULL_HANDLE;
h = hwnd_to_view( w);
while ( h == NULL_HANDLE) {
w = GetWindow( w, cmd2);
if ( !w) return NULL_HANDLE;
h = hwnd_to_view( w);
}
return h;
}
Bool
apc_widget_get_shape( Handle self, Handle mask)
{
HRGN rgn;
int res;
RECT rect;
if ( !mask ) {
rgn = CreateRectRgn(0,0,0,0);
res = GetWindowRgn( HANDLE, rgn);
res = GetClipRgn( sys ps, rgn );
DeleteObject(rgn);
return res != ERROR;
}
rgn = GET_REGION(mask)-> region;
res = GetWindowRgn( HANDLE, rgn);
if ( res == ERROR)
return false;
GetRgnBox(rgn, &rect);
OffsetRgn( rgn, -sys extraPos. x, -sys extraPos. y);
GET_REGION(mask)-> aperture = sys lastSize. y - rect.top;
return true;
}
Bool
apc_widget_get_sync_paint( Handle self)
{
objCheck false;
return is_apt( aptSyncPaint);
}
Bool
apc_widget_get_transparent( Handle self)
{
objCheck false;
return is_apt( aptTransparent);
}
Bool
apc_widget_is_captured( Handle self)
{
objCheck false;
return GetCapture() == ( HWND) var handle;
}
Bool
apc_widget_is_enabled( Handle self)
{
objCheck false;
return is_apt( aptEnabled);
// return IsWindowEnabled( HANDLE);
}
Bool
apc_widget_is_responsive( Handle self)
{
Bool ena = true;
objCheck false;
while ( ena && self != application) {
// ena = IsWindowEnabled( HANDLE);
ena = is_apt( aptEnabled);
self = var owner;
}
return ena;
}
Bool
apc_widget_is_focused( Handle self)
{
objCheck false;
return is_apt( aptFocused);
}
Bool
apc_widget_is_visible( Handle self)
{
objCheck false;
return ( GetWindowLong(HANDLE, GWL_STYLE) & WS_VISIBLE) ? 1 : 0;
}
Bool
apc_widget_is_showing( Handle self)
{
objCheck false;
return IsWindowVisible( HANDLE);
}
Bool
apc_widget_is_exposed( Handle self)
{
HWND h;
HRGN rgnSave = NULL;
HRGN rgn = NULL;
int rgnSaveType, rgnType;
objCheck false;
h = ( HWND) var handle;
if ( !IsWindowVisible( h)) return false;
rgnSave = CreateRectRgn(0,0,0,0);
rgn = CreateRectRgn(0,0,0,0);
rgnSaveType = GetUpdateRgn( h, rgnSave, FALSE);
rgnSaveType = ( rgnSaveType == COMPLEXREGION || rgnSaveType == SIMPLEREGION);
if ( rgnSaveType) ValidateRect( h, NULL);
InvalidateRect( h, NULL, false);
rgnType = GetUpdateRgn( h, rgn, FALSE);
ValidateRect( h, NULL);
if ( rgnSaveType) InvalidateRgn( h, rgnSave, FALSE);
DeleteObject( rgnSave);
DeleteObject( rgn);
return ( rgnType == COMPLEXREGION || rgnType == SIMPLEREGION);
}
Bool
apc_widget_invalidate_rect( Handle self, Rect * rect)
{
PRECT pRect = rect ? map_Rect( self, rect) : NULL;
objCheck false;
if ( !InvalidateRect (( HWND) var handle, pRect, false)) apiErr;
hwnd_repaint_layered( self, false );
if ( is_apt( aptSyncPaint) && !apcUpdateWindow(( HWND) var handle)) apiErr;
objCheck false;
process_transparents( self);
return true;
}
int
apc_widget_scroll( Handle self, int horiz, int vert, Rect * r, Rect *cr, Bool scrollChildren)
{
PRECT pRect = r ? map_Rect( self, r) : NULL;
PRECT pClipRect = cr ? map_Rect( self, cr) : NULL;
Point sz = apc_widget_get_size( self);
int ret;
objCheck scrError;
HideCaret(( HWND) var handle);
if ( pClipRect) {
if ( pClipRect-> left < 0) pClipRect-> left = 0;
if ( pClipRect-> top < 0) pClipRect-> top = 0;
if ( pClipRect-> right > sz. x) pClipRect-> right = sz. x;
if ( pClipRect-> bottom > sz. y) pClipRect-> bottom = sz. y;
}
if ( pRect) {
if ( pRect-> left < -sz. x * 2) pRect-> left = -sz. x * 2;
if ( pRect-> top < -sz. y * 2) pRect-> top = -sz. y * 2;
if ( pRect-> right > sz. x * 2) pRect-> right = sz. x * 2;
if ( pRect-> bottom > sz. y * 2) pRect-> bottom = sz. y * 2;
}
if ( horiz > sz. x || horiz < -sz. x || vert > sz. y || vert < -sz. y) {
if ( pRect && pClipRect) {
RECT rc;
UnionRect( &rc, (RECT*)pRect, (RECT*)pClipRect);
InvalidateRect(( HWND) var handle, &rc, false);
} else
InvalidateRect(( HWND) var handle, pRect ? pRect : pClipRect, false);
ret = scrExpose;
} else {
int rr = ScrollWindowEx(( HWND) var handle,
horiz, -vert, pRect, pClipRect, NULL, NULL,
SW_INVALIDATE | ( scrollChildren ? SW_SCROLLCHILDREN : 0)
);
if (!rr) apiErr;
ret = ( rr == 1 ) ? scrNoExpose : scrExpose;
}
objCheck scrError;
if ( is_apt( aptSyncPaint) && !apcUpdateWindow(( HWND) var handle)) apiErr;
process_transparents( self);
ShowCaret(( HWND) var handle);
return ret;
}
Bool
apc_widget_set_capture( Handle self, Bool capture, Handle confineTo)
{
objCheck false;
if ( capture) {
SetCapture(( HWND) var handle);
if ( confineTo) {
RECT r;
GetWindowRect(( HWND) PComponent( confineTo)-> handle, &r);
if ( !ClipCursor( &r)) apiErrRet;
}
} else {
if ( !ReleaseCapture()) apiErrRet;
if ( !ClipCursor( NULL)) apiErrRet;
}
return true;
}
#define check_swap( parm1, parm2) if ( parm1 > parm2) { int parm3 = parm1; parm1 = parm2; parm2 = parm3;}
Bool
apc_widget_set_clip_by_children( Handle self, Bool clip_by_children)
{
objCheck false;
LONG f;
MSG msg;
Bool is_clipped;
is_clipped = is_apt(aptClipByChildren);
clip_by_children = !!clip_by_children;
if ( is_clipped == clip_by_children )
return true;
if ( sys className == WC_FRAME) {
f = GetWindowLong(( HWND ) var handle, GWL_STYLE);
if ( clip_by_children )
f |= WS_CLIPCHILDREN;
else
f &= ~WS_CLIPCHILDREN;
SetWindowLong(( HWND ) var handle, GWL_STYLE, f);
while ( PeekMessage( &msg, (HWND) var handle, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
}
f = GetWindowLong(HANDLE, GWL_STYLE);
if ( clip_by_children )
f |= WS_CLIPCHILDREN;
else
f &= ~WS_CLIPCHILDREN;
SetWindowLong( HANDLE, GWL_STYLE, f);
while ( PeekMessage( &msg, HANDLE, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
return true;
}
Bool
apc_widget_set_color( Handle self, Color color, int index)
{
Event ev = {cmColorChanged};
objCheck false;
sys viewColors[ index] = color;
ev. gen. source = self;
ev. gen. i = index;
var self-> message( self, &ev);
return true;
}
Bool
apc_widget_set_enabled( Handle self, Bool enable)
{
objCheck false;
apt_assign( aptEnabled, enable);
if (( sys className == WC_FRAME) || ( var owner == application))
EnableWindow( HANDLE, enable);
else
SendMessage( HANDLE, WM_ENABLE, ( WPARAM) enable, 0);
return true;
}
Bool
apc_widget_set_first_click( Handle self, Bool firstClick)
{
objCheck false;
apt_assign( aptFirstClick, firstClick);
return true;
}
Bool
apc_widget_set_focused( Handle self)
{
if ( self && ( self != Application_map_focus( application, self)))
return false;
guts. focSysGranted++;
SetFocus( self ? (( HWND) var handle) : NULL);
guts. focSysGranted--;
return true;
}
Bool
apc_widget_set_font( Handle self, PFont font)
{
Event ev = {cmFontChanged};
objCheck false;
ev. gen. source = self;
var self-> message( self, &ev);
return true;
}
Bool
apc_widget_set_palette( Handle self)
{
objCheck false;
apc_gp_set_palette( self);
if ( guts. displayBMInfo. bmiHeader. biBitCount == 8)
palette_change( self);
return true;
}
Bool
apc_widget_set_pos( Handle self, int x, int y)
{
Handle parent;
Point sz;
RECT r;
objCheck false;
if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);
parent = is_apt( aptClipOwner) ? var owner : application;
sz = ((( PWidget) parent)-> self)-> get_size( parent);
apt_set( aptWinPosDetermined);
if ( sys className == WC_FRAME) {
HWND h = HANDLE;
int ws = apc_window_get_window_state( self);
if (( var stage == csConstructing && ws != wsNormal) || ( ws == wsMinimized)) {
WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
if ( !GetWindowPlacement( h, &w)) apiErrRet;
w. rcNormalPosition. top += sz. y - y - w. rcNormalPosition. bottom;
w. rcNormalPosition. bottom = sz. y - y;
w. rcNormalPosition. right += x - w. rcNormalPosition. left;
w. rcNormalPosition. left = x;
w. flags = 0;
if ( !SetWindowPlacement( h, &w)) apiErrRet;
return true;
}
}
if ( !GetWindowRect( HANDLE, &r)) apiErrRet;
if ( is_apt( aptClipOwner) && ( var owner != application))
MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
if ( sys parentHandle) {
POINT ppos;
ppos. x = x;
ppos. y = dsys( application) lastSize. y - y;
MapWindowPoints( NULL, sys parentHandle, ( LPPOINT)&ppos, 1);
GetWindowRect( sys parentHandle, &r);
x = ppos. x;
y = ppos. y;
} else
y = sz. y - y - r. bottom + r. top;
if ( is_apt(aptLayered) && is_apt(aptRepaintPending)) {
apt_set(aptMovePending);
sys layeredPos. x = x;
sys layeredPos. y = y;
} else {
if ( !SetWindowPos( HANDLE, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) apiErrRet;
}
return true;
}
Bool
apc_widget_set_size( Handle self, int width, int height)
{
RECT r;
HWND h;
objCheck false;
if ( !hwnd_check_limits( width, height, false)) apcErrRet( errInvParams);
h = HANDLE;
if ( sys className == WC_FRAME) {
int ws = apc_window_get_window_state( self);
if (( var stage == csConstructing && ws != wsNormal) || ( ws == wsMinimized)) {
WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
if ( !GetWindowPlacement( h, &w)) apiErrRet;
if ( width < 0) width = 0;
if ( height < 0) height = 0;
w. rcNormalPosition. top = w. rcNormalPosition. bottom - height;
w. rcNormalPosition. right = width + w. rcNormalPosition. left;
w. flags = 0;
if ( !SetWindowPlacement( h, &w)) apiErrRet;
return true;
}
}
if ( !GetWindowRect( h, &r)) apiErrRet;
if ( is_apt( aptClipOwner) && ( var owner != application))
MapWindowPoints( NULL, ( HWND)((( PWidget) var owner)-> handle), ( LPPOINT)&r, 2);
if ( sys parentHandle)
MapWindowPoints( NULL, sys parentHandle, ( LPPOINT)&r, 2);
if ( sys className != WC_FRAME) {
sys sizeLockLevel++;
var virtualSize. x = width;
var virtualSize. y = height;
}
if ( height < 0) height = 0;
if ( width < 0) width = 0;
if ( is_apt(aptMovePending)) {
int dx = r. right - r. left;
int dy = r. bottom - r. top;
r. left = sys layeredPos. x;
r. top = sys layeredPos. y;
r. right = r. left + dx;
r. bottom = r. top + dy;
apt_clear(aptMovePending);
}
if ( !SetWindowPos( h, 0,
r. left, r. bottom - height,
width, height,
SWP_NOZORDER | SWP_NOACTIVATE |
( is_apt( aptWinPosDetermined) ? 0 : SWP_NOMOVE)
)) apiErrRet;
hwnd_repaint_layered( self, false );
if ( sys className != WC_FRAME) sys sizeLockLevel--;
return true;
}
Bool
apc_widget_set_rect( Handle self, int x, int y, int width, int height)
{
HWND h;
Handle parent;
Point sz;
objCheck false;
if ( !hwnd_check_limits( width, height, false)) apcErrRet( errInvParams);
if ( !hwnd_check_limits( x, y, true)) apcErrRet( errInvParams);
parent = is_apt( aptClipOwner) ? var owner : application;
sz = ((( PWidget) parent)-> self)-> get_size( parent);
apt_set( aptWinPosDetermined);
h = HANDLE;
if ( sys className == WC_FRAME) {
int ws = apc_window_get_window_state( self);
if (( var stage == csConstructing && ws != wsNormal) || ( ws == wsMinimized)) {
WINDOWPLACEMENT w = {sizeof(WINDOWPLACEMENT)};
if ( !GetWindowPlacement( h, &w)) apiErrRet;
if ( width < 0) width = 0;
if ( height < 0) height = 0;
w. rcNormalPosition. left = x;
w. rcNormalPosition. bottom = sz. y - y;
w. rcNormalPosition. right = x + width;
w. rcNormalPosition. top = sz. y - y - height;
w. flags = 0;
if ( !SetWindowPlacement( h, &w)) apiErrRet;
return true;
}
}
if ( sys className != WC_FRAME) {
sys sizeLockLevel++;
var virtualSize. x = width;
var virtualSize. y = height;
}
if ( height < 0) height = 0;
if ( width < 0) width = 0;
if ( sys parentHandle) {
POINT ppos;
ppos. x = x;
ppos. y = dsys( application) lastSize. y - y;
MapWindowPoints( NULL, sys parentHandle, ( LPPOINT)&ppos, 1);
x = ppos. x;
y = ppos. y;
} else
y = sz. y - y - height;
apt_clear(aptMovePending);
if ( !SetWindowPos( h, 0, x, y, width, height, SWP_NOZORDER | SWP_NOACTIVATE))
apiErrRet;
hwnd_repaint_layered( self, false );
if ( sys className != WC_FRAME) sys sizeLockLevel--;
return true;
}
Bool
apc_widget_set_size_bounds( Handle self, Point min, Point max)
{
return true;
}
Bool
apc_widget_set_shape( Handle self, Handle mask)
{
HRGN rgn = NULL;
RECT xr;
objCheck false;
if ( !mask) {
if ( sys className == WC_FRAME && is_apt(aptLayered))
SetWindowRgn((HWND) var handle, NULL, true);
else
SetWindowRgn( HANDLE, NULL, true);
hwnd_repaint_layered( self, false );
return true;
}
rgn = CreateRectRgn(0,0,0,0);
CombineRgn( rgn, GET_REGION(mask)->region, NULL, RGN_COPY);
GetRgnBox( rgn, &xr);
sys extraBounds. x = xr. right - 1;
sys extraBounds. y = GET_REGION(mask)->aperture;
if ( sys className == WC_FRAME && !is_apt(aptLayered)) {
Point delta = get_window_borders( sys s. window. borderStyle);
Point sz = apc_widget_get_size( self);
Point p = sys extraBounds;
HRGN r1, r2;
OffsetRgn( rgn, delta.x, sz. y - p.y - delta.y);
sys extraPos. x = delta.x;
sys extraPos. y = sz. y - p.y - delta.y;
r1 = CreateRectRgn( 0, 0, 8192, 8192);
r2 = CreateRectRgn( delta. x, sz. y - delta. y - p.y,
delta.x + p.x, sz. y - delta. y);
CombineRgn( r1, r1, r2, RGN_XOR);
CombineRgn( rgn, rgn, r1, RGN_OR);
DeleteObject( r1);
DeleteObject( r2);
if ( !SetWindowRgn( HANDLE, rgn, true))
apiErrRet;
DeleteObject(rgn);
} else if ( sys className == WC_FRAME ) {
sys extraPos. x = sys extraPos. y = 0;
if ( !SetWindowRgn((HWND) var handle, rgn, true))
apiErrRet;
} else {
sys extraPos. x = sys extraPos. y = 0;
if ( !SetWindowRgn( HANDLE, rgn, true))
apiErrRet;
}
DeleteObject(rgn);
if ( is_apt(aptMovePending)) {
apt_clear(aptMovePending);
if ( !SetWindowPos( HANDLE, 0, sys layeredPos. x, sys layeredPos. y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE))
apiErrRet;
}
hwnd_repaint_layered( self, false );
return true;
}
Bool
apc_widget_set_visible( Handle self, Bool show)
{
objCheck false;
if ( !SetWindowPos( HANDLE, NULL, 0, 0, 0, 0,
( show ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)
| SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) apiErrRet;
objCheck false;
if ( !is_apt( aptClipOwner)) {
InvalidateRect(( HWND) var handle, NULL, false);
objCheck false;
process_transparents( self);
}
hwnd_repaint_layered(self, false);
return true;
}
Bool
apc_widget_set_z_order( Handle self, Handle behind, Bool top)
{
HWND opt = ( top) ? HWND_TOP : HWND_BOTTOM;
objCheck false;
if ( behind != NULL_HANDLE) {
dobjCheck( behind) false;
opt = DHANDLE( behind);
}
if ( !SetWindowPos( HANDLE, opt, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE)) apiErrRet;
return true;
}
Bool
apc_widget_update( Handle self)
{
objCheck false;
if ( !apcUpdateWindow(( HWND) var handle)) apiErrRet;
return true;
}
Bool
apc_widget_validate_rect( Handle self, Rect rect)
{
objCheck false;
if ( !ValidateRect (( HWND) var handle, map_Rect( self, &rect))) apiErrRet;
return true;
}
#ifdef __cplusplus
}
#endif