Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
6158 lines (5690 sloc) 206 KB
/*
###############################################################################
#
# Win32::GUI - Perl-Win32 Graphical User Interface Extension
#
# 29 Jan 1997 by Aldo Calpini <dada@perl.it>
#
# Version: 1.0 (12 Nov 2004)
#
# Copyright (c) 1997..2004 Aldo Calpini. All rights reserved.
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# $Id: GUI.xs,v 1.69 2011/07/16 14:51:03 acalpini Exp $
#
###############################################################################
*/
#include "GUI.h"
#ifdef __CYGWIN__
#include <cygwin/version.h>
#include <sys/cygwin.h>
#endif
/*
###########################################################################
# (@)PACKAGE:Win32::GUI
###########################################################################
*/
MODULE = Win32::GUI PACKAGE = Win32::GUI
PROTOTYPES: DISABLE
##########################################################################
# (@)INTERNAL:_constant(NAME)
DWORD
_constant(name)
char *name
CODE:
if (strEQ(name, "WIN32__GUI__WINDOW"))
RETVAL = WIN32__GUI__WINDOW;
else if (strEQ(name, "WIN32__GUI__DIALOG"))
RETVAL = WIN32__GUI__DIALOG;
else if (strEQ(name, "WIN32__GUI__STATIC"))
RETVAL = WIN32__GUI__STATIC;
else if (strEQ(name, "WIN32__GUI__BUTTON"))
RETVAL = WIN32__GUI__BUTTON;
else if (strEQ(name, "WIN32__GUI__EDIT"))
RETVAL = WIN32__GUI__EDIT;
else if (strEQ(name, "WIN32__GUI__LISTBOX"))
RETVAL = WIN32__GUI__LISTBOX;
else if (strEQ(name, "WIN32__GUI__COMBOBOX"))
RETVAL = WIN32__GUI__COMBOBOX;
else if (strEQ(name, "WIN32__GUI__CHECKBOX"))
RETVAL = WIN32__GUI__CHECKBOX;
else if (strEQ(name, "WIN32__GUI__RADIOBUTTON"))
RETVAL = WIN32__GUI__RADIOBUTTON;
else if (strEQ(name, "WIN32__GUI__TOOLBAR"))
RETVAL = WIN32__GUI__TOOLBAR;
else if (strEQ(name, "WIN32__GUI__PROGRESS"))
RETVAL = WIN32__GUI__PROGRESS;
else if (strEQ(name, "WIN32__GUI__STATUS"))
RETVAL = WIN32__GUI__STATUS;
else if (strEQ(name, "WIN32__GUI__TAB"))
RETVAL = WIN32__GUI__TAB;
else if (strEQ(name, "WIN32__GUI__RICHEDIT"))
RETVAL = WIN32__GUI__RICHEDIT;
else if (strEQ(name, "WIN32__GUI__LISTVIEW"))
RETVAL = WIN32__GUI__LISTVIEW;
else if (strEQ(name, "WIN32__GUI__TREEVIEW"))
RETVAL = WIN32__GUI__TREEVIEW;
else if (strEQ(name, "WIN32__GUI__TRACKBAR"))
RETVAL = WIN32__GUI__TRACKBAR;
else if (strEQ(name, "WIN32__GUI__UPDOWN"))
RETVAL = WIN32__GUI__UPDOWN;
else if (strEQ(name, "WIN32__GUI__TOOLTIP"))
RETVAL = WIN32__GUI__TOOLTIP;
else if (strEQ(name, "WIN32__GUI__ANIMATION"))
RETVAL = WIN32__GUI__ANIMATION;
else if (strEQ(name, "WIN32__GUI__REBAR"))
RETVAL = WIN32__GUI__REBAR;
else if (strEQ(name, "WIN32__GUI__HEADER"))
RETVAL = WIN32__GUI__HEADER;
else if (strEQ(name, "WIN32__GUI__COMBOBOXEX"))
RETVAL = WIN32__GUI__COMBOBOXEX;
else if (strEQ(name, "WIN32__GUI__DTPICK"))
RETVAL = WIN32__GUI__DTPICK;
else if (strEQ(name, "WIN32__GUI__GRAPHIC"))
RETVAL = WIN32__GUI__GRAPHIC;
else if (strEQ(name, "WIN32__GUI__GROUPBOX"))
RETVAL = WIN32__GUI__GROUPBOX;
else if (strEQ(name, "WIN32__GUI__SPLITTER"))
RETVAL = WIN32__GUI__SPLITTER;
else if (strEQ(name, "WIN32__GUI__MDIFRAME"))
RETVAL = WIN32__GUI__MDIFRAME;
else if (strEQ(name, "WIN32__GUI__MDICLIENT"))
RETVAL = WIN32__GUI__MDICLIENT;
else if (strEQ(name, "WIN32__GUI__MDICHILD"))
RETVAL = WIN32__GUI__MDICHILD;
else if (strEQ(name, "WIN32__GUI__MONTHCAL"))
RETVAL = WIN32__GUI__MONTHCAL;
else
RETVAL = 0xFFFFFFFF;
OUTPUT:
RETVAL
##########################################################################
# (@)METHOD:GetAsyncKeyState(keyCode)
# Retrieve the status of the specified virtual key at the time the function
# is called. The status specifies whether the key is up or down.
#
# keyCode -- If A..Z0..9, use the ASCII code. Otherwise, use
# a virtual key code. Example: VK_SHIFT
#
# Return 1 if the key is depressed, 0 if it's not.
LONG
GetAsyncKeyState(key)
int key
CODE:
RETVAL = (GetAsyncKeyState(key) & 0x8000) >>15;
OUTPUT:
RETVAL
##########################################################################
# (@)METHOD:GetKeyState(keyCode)
# Retrieve the status of the specified virtual key at the time the last
# keyboard message was retrieved from the message queue.
#
# In scalar context returns a value specifying whether the key is up(0)
# or down(1). In list context, returns a 2 element list with the first
# element as in scalar context and the second member specifying whether
# the key is toggled(1) or not(0) - this is only meaningful for keys that
# have a toggled state: Caps Lock, Num Lock etc.
#
# keyCode -- If A..Z0..9, use the ASCII code. Otherwise, use
# a virtual key code. Example: VK_SHIFT
void
GetKeyState(key)
int key
PREINIT:
USHORT result;
PPCODE:
result = (USHORT)GetKeyState(key);
if(GIMME_V == G_ARRAY) {
/* list context */
EXTEND(SP, 2);
XST_mIV(0, (UV) ((result & 0x8000) >> 15));
XST_mIV(1, (UV) (result & 0x0001));
XSRETURN(2);
}
else {
/* scalar(and void) context */
XSRETURN_IV((UV) ((result & 0x8000) >> 15));
}
##########################################################################
# (@)METHOD:GetKeyboardState()
# Return array ref with the status of the 256 virtual keys.
#
# The index in the array is the virtual key code. If the value
# is true, that key is depressed.
#
# Example:
# $key=Win32::GUI::GetKeyboardState;
# print 'CTRL is down' if $key->[0x11];
AV*
GetKeyboardState()
PREINIT:
AV *array;
BYTE keys[256];
int i;
CODE:
GetKeyboardState(keys);
array = (AV*)sv_2mortal((SV*)newAV());
for(i = 0; i <= 256; i++) {
av_push(array, newSViv(keys[i] & 128));
}
RETVAL = array;
OUTPUT:
RETVAL
##########################################################################
# (@)METHOD:LoadLibrary(NAME)
# The LoadLibrary function maps the specified executable module into the
# address space of the calling process.
#
# The return value is a handle to the module, or undef on failure.
#
# Directory seperators are normalised to windows seperators (C<\>).
#
# Under Cygwin, cygwin paths are converted to windows paths
HINSTANCE
LoadLibrary(name)
char *name;
PREINIT:
char buffer[MAX_PATH+1];
int i;
CODE:
#ifdef __CYGWIN__
/* Under Cygwin, convert paths to windows
* paths. E.g. convert /usr/local... and /cygdrive/c/...
*/
#if CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR >= 181
i = cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE,name,buffer,MAX_PATH+1);
if (i < 0) XSRETURN_UNDEF;
#else
/* old cygwin api */
if(cygwin_conv_to_win32_path(name,buffer) != 0)
XSRETURN_UNDEF;
#endif
#else
/* LoadLibrary on Win98 (at least) doesn't like unix
* path seperators, so normalise to windows path seperators
*/
for(i=0; *name && (i<MAX_PATH); ++name,++i) {
buffer[i] = (*name == '/' ? '\\' : *name);
}
if(*name) {
/* XXX Path too long - although this appears to be what
* LoadLibrary would return with such a path, it might be
* better to find a more specific error code. E.g.
* ENAMETOOLONG?
*/
SetLastError(ERROR_FILE_NOT_FOUND);
errno = ENOENT;
XSRETURN_UNDEF;
}
buffer[i] = 0;
#endif
RETVAL = LoadLibrary(buffer);
if(!RETVAL)
XSRETURN_UNDEF;
OUTPUT:
RETVAL
##########################################################################
# (@)METHOD:FreeLibrary(LIBRARY)
# The FreeLibrary function decrements the reference count of the loaded dynamic-link library (DLL) module.
bool
FreeLibrary(library)
HINSTANCE library;
CODE:
RETVAL = FreeLibrary(library);
OUTPUT:
RETVAL
##########################################################################
# (@)METHOD:GetEvent(NAME)
# Retrieves an event. If the New Event Model is being used, this will
# return the code-reference of the event you named, otherwise it will
# return undef.
void
GetEvent(handle,name)
HWND handle
char * name
PREINIT:
SV** eventhandler;
LPPERLWIN32GUI_USERDATA perlud;
PPCODE:
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr((HWND) handle, GWLP_USERDATA);
if(perlud == NULL || perlud->hvEvents == NULL) XSRETURN_UNDEF;
eventhandler = hv_fetch(perlud->hvEvents,name,strlen(name),0);
if(eventhandler != NULL) {
SvREFCNT_inc(*eventhandler);
XPUSHs(*eventhandler);
XSRETURN(1);
}
XSRETURN_UNDEF;
##########################################################################
# (@)METHOD:SetEvent(NAME,HANDLER)
# Sets an event. If the New Event Model is being used, this will enable
# the specified event and set it to be handled by the specified C<HANDLER>,
# which should be a code-reference.
void
SetEvent(handle,name,event)
HWND handle
char * name
SV* event
PREINIT:
LPPERLWIN32GUI_USERDATA perlud;
PERLWIN32GUI_CREATESTRUCT perlcs;
PPCODE:
ZeroMemory(&perlcs, sizeof(PERLWIN32GUI_CREATESTRUCT));
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr((HWND) handle, GWLP_USERDATA);
if(perlud == NULL) XSRETURN_UNDEF;
if ( perlud->hvEvents == NULL ) {
perlud->hvEvents = newHV();
perlud->dwEventMask = 0;
}
if(perlud->hvEvents == NULL) XSRETURN_UNDEF;
perlcs.iClass = perlud->iClass;
perlcs.hvEvents = perlud->hvEvents;
perlcs.dwEventMask = perlud->dwEventMask;
ParseNEMEvent(NOTXSCALL &perlcs, name, event);
perlud->hvEvents = perlcs.hvEvents;
perlud->dwEventMask = perlcs.dwEventMask;
SwitchBit(perlud->dwPlStyle, PERLWIN32GUI_NEM, (perlud->dwEventMask != 0));
XSRETURN_YES;
##########################################################################
# (@)METHOD:LoadResource(NAME)
# Loads a generic resource from the EXE file that your perl process is
# running as. This is for use when distributing your application. Resources
# can be packed into the EXE file using many tools including ResHacker.
#
# Note that packing resources into a PAR executable will not work. You must
# first pack the resources into par.exe then use PAR to build your
# executable.
#
# For this routine to work, any resources you wish to load with it must
# be added to the executable with the RCDATA resource type.
#
# If the resource is not found in the EXE, this function will return NULL,
# otherwise it will return a scalar containing the raw resource data.
void
LoadResource(filename)
LPCSTR filename
PPCODE:
HINSTANCE myInstance;
HRSRC resInfo;
HGLOBAL resHandle;
char * resData;
DWORD resSize;
myInstance = GetModuleHandle(NULL);
if(myInstance == NULL) XSRETURN_UNDEF;
resInfo = FindResource(myInstance,filename,RT_RCDATA);
if(resInfo == NULL) XSRETURN_UNDEF;
resSize = SizeofResource(myInstance,resInfo);
resHandle = LoadResource(myInstance,resInfo);
if(resHandle == NULL) XSRETURN_UNDEF;
resData = (char *) LockResource(resHandle);
if(resData != NULL) {
// Whew, we have a pointer to our resource data.
// We would free here, but according to MSDN we don't have to (?!)
XPUSHs(newSVpvn(resData, resSize));
XSRETURN(1);
}
XSRETURN_UNDEF;
##########################################################################
# (@)METHOD:GetPerlWindow()
# Returns the handle of the command prompt window your perl script is
# running in; if called in an array context, returns the handle and the
# HINSTANCE of your perl process.
void
GetPerlWindow()
PPCODE:
char OldPerlWindowTitle[1024];
char NewPerlWindowTitle[1024];
HWND hwndFound;
HINSTANCE hinstanceFound;
// this is an hack from M$'s Knowledge Base
// to get the HWND of the console in which
// Perl is running (and Hide() it :-).
GetConsoleTitle(OldPerlWindowTitle, 1024);
wsprintf(NewPerlWindowTitle,
"PERL-%d-%d",
GetTickCount(),
GetCurrentProcessId());
SetConsoleTitle(NewPerlWindowTitle);
Sleep(40);
hwndFound = FindWindow(NULL, NewPerlWindowTitle);
// another hack to get the program's instance
#ifdef NT_BUILD_NUMBER
hinstanceFound = GetModuleHandle("GUI.PLL");
#else
hinstanceFound = GetModuleHandle("GUI.DLL");
#endif
// hinstanceFound = (HINSTANCE) GetWindowLongPtr(hwndFound, GWL_HINSTANCE);
// sv_hinstance = perl_get_sv("Win32::GUI::hinstance", TRUE);
// sv_setiv(sv_hinstance, PTR2IV(hinstanceFound));
SetConsoleTitle(OldPerlWindowTitle);
if(GIMME == G_ARRAY) {
EXTEND(SP, 2);
XST_mIV(0, PTR2IV(hwndFound));
XST_mIV(1, PTR2IV(hinstanceFound));
XSRETURN(2);
} else {
XSRETURN_IV(PTR2IV(hwndFound));
}
##########################################################################
# (@)INTERNAL:RegisterClassEx(%OPTIONS)
# used by new Win32::GUI::Class
void
RegisterClassEx(...)
PPCODE:
WNDCLASSEX wcx;
HINSTANCE hinstance;
char * option;
int i, next_i;
WNDPROC DefClassProc = NULL;
ZeroMemory(&wcx, sizeof(WNDCLASSEX));
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_HREDRAW | CS_VREDRAW; // TODO (default class style...)
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.lpfnWndProc = WindowMsgLoop;
#ifdef NT_BUILD_NUMBER
hinstance = GetModuleHandle("GUI.PLL");
#else
hinstance = GetModuleHandle("GUI.DLL");
#endif
wcx.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_DEFAULTICON));
wcx.hIconSm = NULL;
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.lpszMenuName = NULL;
for(i = 0; i < items; i++) {
if(strcmp(SvPV_nolen(ST(i)), "-extends") == 0) {
next_i = i + 1;
if(!GetClassInfoEx((HINSTANCE) NULL, (LPCTSTR) SvPV_nolen(ST(next_i)), &wcx)) {
W32G_WARN("Win32::GUI: Class '%s' not found!", SvPV_nolen(ST(next_i)));
XSRETURN_NO;
}
DefClassProc = wcx.lpfnWndProc;
}
}
next_i = -1;
for(i = 0; i < items; i++) {
if(next_i == -1) {
option = SvPV_nolen(ST(i));
if(strcmp(option, "-name") == 0) {
next_i = i + 1;
wcx.lpszClassName = (char *) SvPV_nolen(ST(next_i));
} else if(strcmp(option, "-color") == 0) {
next_i = i + 1;
wcx.hbrBackground = (HBRUSH) SvCOLORREF(NOTXSCALL ST(next_i));
} else if(strcmp(option, "-brush") == 0) {
next_i = i + 1;
wcx.hbrBackground = (HBRUSH) handle_From(NOTXSCALL ST(next_i));
} else if(strcmp(option, "-visual") == 0) {
next_i = i + 1;
// -visual => 0 is obsolete
} else if(strcmp(option, "-widget") == 0) {
next_i = i + 1;
if(strcmp(SvPV_nolen(ST(next_i)), "Container") == 0) {
wcx.lpfnWndProc = ContainerMsgLoop;
} else if(strcmp(SvPV_nolen(ST(next_i)), "Graphic") == 0) {
wcx.lpfnWndProc = CustomMsgLoop;
} else if(strcmp(SvPV_nolen(ST(next_i)), "Splitter") == 0) {
wcx.lpfnWndProc = CustomMsgLoop;
wcx.hCursor = LoadCursor(hinstance, MAKEINTRESOURCE(IDC_HSPLIT));
} else if(strcmp(SvPV_nolen(ST(next_i)), "SplitterH") == 0) {
wcx.lpfnWndProc = CustomMsgLoop;
wcx.hCursor = LoadCursor(hinstance, MAKEINTRESOURCE(IDC_VSPLIT));
} else if(strcmp(SvPV_nolen(ST(next_i)), "MDIFrame") == 0) {
wcx.lpfnWndProc = MDIFrameMsgLoop;
} else if(strcmp(SvPV_nolen(ST(next_i)), "MDIChild") == 0) {
wcx.lpfnWndProc = MDIChildMsgLoop;
} else {
wcx.lpfnWndProc = ControlMsgLoop;
}
} else if(strcmp(option, "-style") == 0) {
next_i = i + 1;
wcx.style = (UINT)SvIV(ST(next_i));
} else if(strcmp(option, "-icon") == 0) {
next_i = i + 1;
wcx.hIcon = (HICON) handle_From(NOTXSCALL ST(next_i));
} else if(strcmp(option, "-cursor") == 0) {
next_i = i + 1;
wcx.hCursor = (HCURSOR) handle_From(NOTXSCALL ST(next_i));
} else if(strcmp(option, "-menu") == 0) {
next_i = i + 1;
wcx.lpszMenuName = (char *) SvPV_nolen(ST(next_i));
}
} else {
next_i = -1;
}
}
// Register the window class.
if(RegisterClassEx(&wcx)) {
if (DefClassProc != NULL && DefClassProc != wcx.lpfnWndProc)
SetDefClassProc (NOTXSCALL wcx.lpszClassName, DefClassProc);
XSRETURN_YES;
// Try to reregister
} else if ( UnregisterClass( wcx.lpszClassName, wcx.hInstance ) ) {
if( RegisterClassEx(&wcx) ) {
if (DefClassProc != NULL && DefClassProc != wcx.lpfnWndProc)
SetDefClassProc (NOTXSCALL wcx.lpszClassName, DefClassProc);
XSRETURN_YES;
}
}
XSRETURN_NO;
##########################################################################
# (@)INTERNAL:CreateWindowEx(%OPTIONS)
# obsoleted, use Create() instead
void
CreateWindowEx(...)
PPCODE:
HWND myhandle;
int i, next_i;
HWND hParent;
HMENU hMenu;
HINSTANCE hInstance;
LPVOID pPointer;
DWORD dwStyle;
DWORD dwExStyle;
LPCTSTR szClassname;
LPCTSTR szText;
int nX, nY, nWidth, nHeight;
char * option;
hParent = NULL;
hMenu = NULL;
hInstance = NULL;
pPointer = NULL;
dwStyle = 0;
dwExStyle = 0;
szText = NULL;
next_i = -1;
for(i = 0; i < items; i++) {
if(next_i == -1) {
option = SvPV_nolen(ST(i));
if(strcmp(option, "-exstyle") == 0) {
next_i = i + 1;
dwExStyle = (DWORD) SvIV(ST(next_i));
}
if(strcmp(option, "-class") == 0) {
next_i = i + 1;
szClassname = (LPCTSTR) SvPV_nolen(ST(next_i));
}
if(strcmp(option, "-text") == 0
|| strcmp(option, "-title") == 0) {
next_i = i + 1;
szText = (LPCTSTR) SvPV_nolen(ST(next_i));
}
if(strcmp(option, "-style") == 0) {
next_i = i + 1;
dwStyle = (DWORD) SvIV(ST(next_i));
}
if(strcmp(option, "-left") == 0) {
next_i = i + 1;
nX = (int) SvIV(ST(next_i));
}
if(strcmp(option, "-top") == 0) {
next_i = i + 1;
nY = (int) SvIV(ST(next_i));
}
if(strcmp(option, "-height") == 0) {
next_i = i + 1;
nHeight = (int) SvIV(ST(next_i));
}
if(strcmp(option, "-width") == 0) {
next_i = i + 1;
nWidth = (int) SvIV(ST(next_i));
}
if(strcmp(option, "-parent") == 0) {
next_i = i + 1;
hParent = (HWND) handle_From(NOTXSCALL ST(next_i));
}
if(strcmp(option, "-menu") == 0) {
next_i = i + 1;
hMenu = (HMENU) handle_From(NOTXSCALL ST(next_i));
}
if(strcmp(option, "-instance") == 0) {
next_i = i + 1;
hInstance = INT2PTR(HINSTANCE,SvIV(ST(next_i)));
}
if(strcmp(option, "-data") == 0) {
next_i = i + 1;
pPointer = (LPVOID) SvPV_nolen(ST(next_i));
}
} else {
next_i = -1;
}
}
#ifdef PERLWIN32GUI_DEBUG
printf("XS(CreateWindowEx): Done parsing parameters...\n");
printf("XS(CreateWindowEx): dwExStyle = 0x%x\n", dwExStyle);
printf("XS(CreateWindowEx): szClassname = %s\n", szClassname);
printf("XS(CreateWindowEx): szText = %s\n", szText);
printf("XS(CreateWindowEx): dwStyle = 0x%x\n", dwStyle);
printf("XS(CreateWindowEx): nX = %d\n", nX);
printf("XS(CreateWindowEx): nY = %d\n", nY);
printf("XS(CreateWindowEx): nWidth = %d\n", nWidth);
printf("XS(CreateWindowEx): nHeight = %d\n", nHeight);
printf("XS(CreateWindowEx): hParent = 0x%x\n", hParent);
printf("XS(CreateWindowEx): hMenu = 0x%x\n", hMenu);
printf("XS(CreateWindowEx): hInstance = 0x%x\n", hInstance);
printf("XS(CreateWindowEx): pPointer = 0x%x\n", pPointer);
#endif
if(myhandle = CreateWindowEx(dwExStyle,
szClassname,
szText,
dwStyle,
nX,
nY,
nWidth,
nHeight,
hParent,
hMenu,
hInstance,
pPointer)) {
XSRETURN_IV(PTR2IV(myhandle));
} else {
XSRETURN_NO;
}
###########################################################################
# (@)INTERNAL:Create(%OPTIONS)
# this is where all the windows are created
void
Create(...)
PPCODE:
HWND myhandle;
int first_i;
PERLWIN32GUI_CREATESTRUCT perlcs;
LPVOID pPointer;
SV* self;
SV** stored;
SV* storing;
SV** font;
LPPERLWIN32GUI_USERDATA perlud;
ZeroMemory(&perlcs, sizeof(PERLWIN32GUI_CREATESTRUCT));
self = newSVsv(ST(0));
sv_rvweaken(self);
perlcs.cs.hInstance = GetModuleHandle(NULL);
perlcs.hvSelf = (HV*) SvRV(self);
perlcs.iClass = (int)SvIV(ST(1));
perlcs.clrForeground = CLR_INVALID;
perlcs.clrBackground = CLR_INVALID;
perlcs.iMinWidth = -1;
perlcs.iMaxWidth = -1;
perlcs.iMinHeight = -1;
perlcs.iMaxHeight = -1;
// #### fill the default parameters for classes
OnPreCreate[perlcs.iClass](NOTXSCALL &perlcs);
first_i = 2;
if(SvROK(ST(2))) {
perlcs.cs.hwndParent = (HWND) handle_From(NOTXSCALL ST(2));
perlcs.hvParent = (HV*) SvRV(ST(2));
first_i = 3;
}
// #### options parsing loop
ParseWindowOptions(NOTXSCALL sp, mark, ax, items, first_i, &perlcs);
// No event model set, then force default event model.
if ( !(perlcs.dwPlStyle & PERLWIN32GUI_OEM) & !(perlcs.dwPlStyle & PERLWIN32GUI_NEM)) {
SwitchBit(perlcs.dwPlStyle, PERLWIN32GUI_OEM, 1);
}
// #### post-processing default parameters
switch(perlcs.iClass) {
case WIN32__GUI__BUTTON:
CalcControlSize(NOTXSCALL &perlcs, 16, 8);
break;
case WIN32__GUI__CHECKBOX:
case WIN32__GUI__RADIOBUTTON:
CalcControlSize(NOTXSCALL &perlcs, 24, 8);
break;
case WIN32__GUI__STATIC:
CalcControlSize(NOTXSCALL &perlcs, 0, 0);
break;
}
// #### default styles for all controls
if(perlcs.iClass != WIN32__GUI__WINDOW &&
perlcs.iClass != WIN32__GUI__DIALOG &&
perlcs.iClass != WIN32__GUI__MDIFRAME &&
perlcs.iClass != WIN32__GUI__MDICHILD &&
perlcs.iClass != WIN32__GUI__TOOLTIP ) {
SwitchBit(perlcs.cs.style, WS_CHILD, 1);
}
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): Done parsing parameters...\n");
printf("XS(Create): dwExStyle = 0x%x\n", perlcs.cs.dwExStyle);
printf("XS(Create): szClassname = '%s'\n", perlcs.cs.lpszClass);
printf("XS(Create): szName = '%s'\n", perlcs.cs.lpszName);
printf("XS(Create): dwStyle = 0x%x\n", perlcs.cs.style);
printf("XS(Create): nX = %d\n", perlcs.cs.x);
printf("XS(Create): nY = %d\n", perlcs.cs.y);
printf("XS(Create): nWidth = %d\n", perlcs.cs.cx);
printf("XS(Create): nHeight = %d\n", perlcs.cs.cy);
printf("XS(Create): hParent = 0x%x\n", perlcs.cs.hwndParent);
printf("XS(Create): hMenu = 0x%x\n", perlcs.cs.hMenu);
printf("XS(Create): hInstance = 0x%x\n", perlcs.cs.hInstance);
printf("XS(Create): dwPlStyle = 0x%x\n", perlcs.dwPlStyle);
#endif
// #### prepare the ground for the window
Newz(0, perlud, 1, PERLWIN32GUI_USERDATA);
perlud->dwSize = sizeof(PERLWIN32GUI_USERDATA);
PERLUD_STORE;
perlud->svSelf = self;
if (NULL != perlcs.szWindowName) {
strcpy( perlud->szWindowName, perlcs.szWindowName);
} else {
sprintf(perlud->szWindowName, "#%x", perlud);
perlcs.szWindowName = perlud->szWindowName;
}
perlud->iClass = perlcs.iClass;
perlud->hAcc = perlcs.hAcc;
perlud->hCursor = perlcs.hCursor;
perlud->dwPlStyle = perlcs.dwPlStyle;
perlud->iMinWidth = perlcs.iMinWidth;
perlud->iMaxWidth = perlcs.iMaxWidth;
perlud->iMinHeight = perlcs.iMinHeight;
perlud->iMaxHeight = perlcs.iMaxHeight;
perlud->clrForeground = perlcs.clrForeground;
perlud->clrBackground = perlcs.clrBackground;
perlud->hBackgroundBrush = perlcs.hBackgroundBrush;
perlud->bDeleteBackgroundBrush = perlcs.bDeleteBackgroundBrush;
perlud->hvEvents = perlcs.hvEvents;
perlud->dwEventMask = perlcs.dwEventMask;
perlud->dwData = PTR2IV(perlcs.cs.lpCreateParams);
pPointer = perlud;
// #### the following can be vital for the window
// #### because as soon as it is created the message
// #### loop is activated and data needs to be there
storing = newSViv((IV) perlcs.iClass);
stored = hv_store_mg(NOTXSCALL perlcs.hvSelf, "-type", 5, storing, 0); // TODO : used ?
storing = newSVpv((char *)perlcs.szWindowName, 0);
stored = hv_store_mg(NOTXSCALL perlcs.hvSelf, "-name", 5, storing, 0);
// Specific MDI_CLIENT : Send CLIENTCREATESTRUCT as LPARAM
if(perlcs.iClass == WIN32__GUI__MDICLIENT ) {
pPointer = perlcs.cs.lpCreateParams;
}
// #### and finally, creation of the window
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): Done initialization of USERDATA struct...\n");
#endif
if(myhandle = CreateWindowEx(
perlcs.cs.dwExStyle,
perlcs.cs.lpszClass,
perlcs.cs.lpszName,
perlcs.cs.style,
perlcs.cs.x,
perlcs.cs.y,
perlcs.cs.cx,
perlcs.cs.cy,
perlcs.cs.hwndParent,
perlcs.cs.hMenu,
perlcs.cs.hInstance,
pPointer
)) {
// #### ok, we can fill this object's hash
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): storing -handle...\n");
#endif
storing = newSViv(PTR2IV(myhandle));
stored = hv_store_mg(NOTXSCALL perlcs.hvSelf, "-handle", 7, storing, 0);
// #### set the font for the control
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): storing -font...\n");
#endif
if(perlcs.hFont != NULL) {
storing = newSViv(PTR2IV(perlcs.hFont));
stored = hv_store_mg(NOTXSCALL perlcs.hvSelf, "-font", 5, storing, 0);
SendMessage(myhandle, WM_SETFONT, (WPARAM) perlcs.hFont, 0);
} else if(perlcs.cs.hwndParent != NULL && perlcs.hvParent != NULL) {
font = hv_fetch_mg(NOTXSCALL perlcs.hvParent, "-font", 5, FALSE);
if(font != NULL && SvOK(*font)) {
perlcs.hFont = (HFONT) handle_From(NOTXSCALL *font);
SendMessage(myhandle, WM_SETFONT, (WPARAM) perlcs.hFont, 0);
} else {
perlcs.hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
SendMessage(myhandle, WM_SETFONT, (WPARAM) perlcs.hFont, 0);
}
}
if(NULL == perlcs.hAcc) {
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): storing -accel...\n");
#endif
stored = hv_store_mg(NOTXSCALL perlcs.hvSelf, "-accel", 6, newSViv(0), 0);
}
// #### add (or create) the tooltip
if(perlcs.szTip != NULL) {
if(perlcs.hvParent != NULL) {
if(perlcs.hTooltip == NULL) {
SV** t;
t = hv_fetch_mg(NOTXSCALL perlcs.hvParent, "-tooltip", 8, 0);
if(t != NULL && SvOK( *t )) {
perlcs.hTooltip = INT2PTR(HWND,SvIV(*t));
}
}
if(perlcs.hTooltip == NULL) {
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): creating -tooltip...\n");
#endif
perlcs.hTooltip = CreateTooltip(NOTXSCALL perlcs.hvParent);
}
}
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): adding -tooltip...\n");
#endif
TOOLINFO ti;
ZeroMemory(&ti, sizeof(TOOLINFO));
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_IDISHWND | TTF_CENTERTIP | TTF_SUBCLASS;
ti.hwnd = perlcs.cs.hwndParent;
ti.uId = (WPARAM) myhandle;
ti.lpszText = perlcs.szTip;
SendMessage(perlcs.hTooltip, TTM_ADDTOOL, 0, (LPARAM) &ti);
}
// #### store the child in the parent hash
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): storing child into parent...\n");
#endif
if(perlcs.hvParent != NULL && perlcs.szWindowName != NULL) {
// storing = newSVsv(ST(0));
// sv_rvweaken(storing);
storing = SvREFCNT_inc (self);
stored = hv_store_mg(NOTXSCALL perlcs.hvParent, perlcs.szWindowName, strlen(perlcs.szWindowName), storing, 0);
}
// #### other post-creation class-specific initializations...
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): post-creation phase...\n");
#endif
OnPostCreate[perlcs.iClass](NOTXSCALL myhandle, &perlcs);
// #### store a pointer to the Perl object in the window's USERDATA
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): storing GWLP_USERDATA...\n");
#endif
// Specific MDI_CLIENT : SubClass Window
// We need subclass after window creation for IDFirstChild work.
if(perlcs.iClass == WIN32__GUI__MDICLIENT ) {
perlud->dwPlStyle |= PERLWIN32GUI_CUSTOMCLASS;
perlud->WndProc = (WNDPROC) SetWindowLongPtr(myhandle, GWLP_WNDPROC, (LONG_PTR) MDIClientMsgLoop);
SetWindowLongPtr(myhandle, GWLP_USERDATA, (LONG_PTR) perlud);
}
// Sub class all standard window control as child control (no WM_CREATE or WN_NCCREATE catch)
if( !(perlud->dwPlStyle & PERLWIN32GUI_CUSTOMCLASS) ) {
LPPERLWIN32GUI_USERDATA testud;
testud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(myhandle, GWLP_USERDATA);
if (!ValidUserData(testud) ) {
perlud->WndProc = (WNDPROC) SetWindowLongPtr(myhandle, GWLP_WNDPROC, (LONG_PTR) ControlMsgLoop);
SetWindowLongPtr(myhandle, GWLP_USERDATA, (LONG_PTR) perlud);
}
}
// #### (try to) figure out which MsgLoop procedure to use
if (perlcs.hvParent != NULL) {
LPPERLWIN32GUI_USERDATA parentud;
parentud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(perlcs.cs.hwndParent, GWLP_USERDATA);
if( ValidUserData(parentud) ) {
if(parentud->iClass != WIN32__GUI__WINDOW &&
parentud->iClass != WIN32__GUI__DIALOG &&
parentud->iClass != WIN32__GUI__MDIFRAME &&
parentud->iClass != WIN32__GUI__MDICLIENT &&
!(parentud->dwPlStyle & PERLWIN32GUI_CONTAINER)) {
SwitchBit(parentud->dwPlStyle, PERLWIN32GUI_CONTAINER, 1);
}
}
}
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): DONE!\n");
#endif
XSRETURN_IV(PTR2IV(myhandle));
} else {
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Create): CreateWindowEx failed, returning undef\n");
#endif
XSRETURN_NO;
}
###########################################################################
# (@)METHOD:Change(HANDLE, %OPTIONS)
# Change most of the options used when the object was created.
void
Change(...)
PPCODE:
HWND handle;
PERLWIN32GUI_CREATESTRUCT perlcs;
LPPERLWIN32GUI_USERDATA perlud;
handle = (HWND) handle_From(NOTXSCALL ST(0));
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(handle, GWLP_USERDATA);
ZeroMemory(&perlcs, sizeof(PERLWIN32GUI_CREATESTRUCT));
if( ! ValidUserData(perlud) ) {
XSRETURN_UNDEF;
}
perlcs.hvSelf = (HV*) SvRV(perlud->svSelf);
perlcs.cs.style = (LONG)GetWindowLongPtr(handle, GWL_STYLE);
perlcs.cs.dwExStyle = (DWORD)GetWindowLongPtr(handle, GWL_EXSTYLE);
if(perlcs.hvSelf != NULL) {
// #### retrieve windows data
perlcs.iClass = perlud->iClass;
perlcs.hAcc = perlud->hAcc;
perlcs.hCursor = perlud->hCursor;
perlcs.dwPlStyle= perlud->dwPlStyle;
perlcs.iMinWidth = perlud->iMinWidth;
perlcs.iMaxWidth = perlud->iMaxWidth;
perlcs.iMinHeight = perlud->iMinHeight;
perlcs.iMaxHeight = perlud->iMaxHeight;
perlcs.clrForeground = perlud->clrForeground;
perlcs.clrBackground = perlud->clrBackground;
perlcs.hBackgroundBrush = perlud->hBackgroundBrush;
perlcs.bDeleteBackgroundBrush = perlud->bDeleteBackgroundBrush;
perlcs.hvEvents = perlud->hvEvents;
perlcs.dwEventMask = perlud->dwEventMask;
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Change): BEFORE dwExStyle = 0x%x\n", perlcs.cs.dwExStyle);
printf("XS(Change): BEFORE szClassname = %s\n", perlcs.cs.lpszClass);
printf("XS(Change): BEFORE szName = %s\n", perlcs.cs.lpszName);
printf("XS(Change): BEFORE dwStyle = 0x%x\n", perlcs.cs.style);
printf("XS(Change): BEFORE nX = %d\n", perlcs.cs.x);
printf("XS(Change): BEFORE nY = %d\n", perlcs.cs.y);
printf("XS(Change): BEFORE nWidth = %d\n", perlcs.cs.cx);
printf("XS(Change): BEFORE nHeight = %d\n", perlcs.cs.cy);
printf("XS(Change): BEFORE hParent = 0x%x\n", perlcs.cs.hwndParent);
printf("XS(Change): BEFORE hMenu = 0x%x\n", perlcs.cs.hMenu);
printf("XS(Change): BEFORE hInstance = 0x%x\n", perlcs.cs.hInstance);
printf("XS(Change): BEFORE clrForeground = 0x%x\n", perlcs.clrForeground);
printf("XS(Change): BEFORE clrBackground = 0x%x\n", perlcs.clrBackground);
printf("XS(Change): BEFORE hBackgroundBrush = 0x%x\n", perlcs.hBackgroundBrush);
printf("XS(Change): BEFORE bDeleteBackgroundBrush = %d\n", perlcs.bDeleteBackgroundBrush);
#endif
// #### parse new window options
ParseWindowOptions(NOTXSCALL sp, mark, ax, items, 1, &perlcs);
// #### default styles for all controls
if(perlcs.iClass != WIN32__GUI__WINDOW &&
perlcs.iClass != WIN32__GUI__DIALOG &&
perlcs.iClass != WIN32__GUI__MDIFRAME &&
perlcs.iClass != WIN32__GUI__MDICHILD) {
SwitchBit(perlcs.cs.style, WS_CHILD, 1);
}
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(Change): AFTER dwExStyle = 0x%x\n", perlcs.cs.dwExStyle);
printf("XS(Change): AFTER szClassname = %s\n", perlcs.cs.lpszClass);
printf("XS(Change): AFTER szName = %s\n", perlcs.cs.lpszName);
printf("XS(Change): AFTER dwStyle = 0x%x\n", perlcs.cs.style);
printf("XS(Change): AFTER nX = %d\n", perlcs.cs.x);
printf("XS(Change): AFTER nY = %d\n", perlcs.cs.y);
printf("XS(Change): AFTER nWidth = %d\n", perlcs.cs.cx);
printf("XS(Change): AFTER nHeight = %d\n", perlcs.cs.cy);
printf("XS(Change): AFTER hParent = 0x%x\n", perlcs.cs.hwndParent);
printf("XS(Change): AFTER hMenu = 0x%x\n", perlcs.cs.hMenu);
printf("XS(Change): AFTER hInstance = 0x%x\n", perlcs.cs.hInstance);
printf("XS(Change): AFTER clrForeground = 0x%x\n", perlcs.clrForeground);
printf("XS(Change): AFTER clrBackground = 0x%x\n", perlcs.clrBackground);
printf("XS(Change): AFTER hBackgroundBrush = 0x%x\n", perlcs.hBackgroundBrush);
printf("XS(Change): AFTER bDeleteBackgroundBrush = %d\n", perlcs.bDeleteBackgroundBrush);
#endif
// #### Perform changes
if(NULL != perlcs.szWindowName) {
strcpy(perlud->szWindowName, perlcs.szWindowName);
}
perlud->iClass = perlcs.iClass;
perlud->hAcc = perlcs.hAcc;
perlud->hCursor = perlcs.hCursor;
perlud->dwPlStyle= perlcs.dwPlStyle;
perlud->iMinWidth = perlcs.iMinWidth;
perlud->iMaxWidth = perlcs.iMaxWidth;
perlud->iMinHeight = perlcs.iMinHeight;
perlud->iMaxHeight = perlcs.iMaxHeight;
perlud->clrForeground = perlcs.clrForeground;
perlud->clrBackground = perlcs.clrBackground;
perlud->hBackgroundBrush = perlcs.hBackgroundBrush;
perlud->bDeleteBackgroundBrush = perlcs.bDeleteBackgroundBrush;
perlud->hvEvents = perlcs.hvEvents;
perlud->dwEventMask = perlcs.dwEventMask;
if(perlcs.cs.lpszName != NULL)
SetWindowText(handle, perlcs.cs.lpszName);
SetWindowLongPtr(handle, GWL_STYLE, perlcs.cs.style);
SetWindowLongPtr(handle, GWL_EXSTYLE, perlcs.cs.dwExStyle);
if(perlcs.cs.x != 0 || perlcs.cs.y != 0)
SetWindowPos(handle, (HWND) NULL, perlcs.cs.x, perlcs.cs.y, 0, 0,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSIZE);
if(perlcs.cs.cx != 0 || perlcs.cs.cy != 0)
SetWindowPos(handle, (HWND) NULL, 0, 0, perlcs.cs.cx, perlcs.cs.cy,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE);
if(perlcs.cs.hMenu != NULL)
SetMenu(handle, perlcs.cs.hMenu);
if(perlcs.hFont != NULL) {
hv_store_mg(NOTXSCALL perlcs.hvSelf, "-font", 5, newSViv(PTR2IV(perlcs.hFont)), 0);
SendMessage(handle, WM_SETFONT, (WPARAM) perlcs.hFont, 0);
}
// ### Class Post creation
OnPostCreate[perlcs.iClass](NOTXSCALL handle, &perlcs);
/* TODO: change class ???
if(perlcs.cs.iClass != NULL)
SetWindowLong(handle, GWL_
*/
XSRETURN_YES;
} else {
XSRETURN_NO;
}
###########################################################################
# (@)METHOD:Dialog()
# Enter the GUI dialog phase: the script halts, the user can interact with
# the created windows and events subroutines are triggered as necessary;
# note that this function must be called without ANY parameter or
# instantiation (eg. don't call it as method of a created object):
#
# Win32::GUI::Dialog(); # correct
# $Window->Dialog(); # !!!WRONG!!!
#
# Win32::GUI::Dialog(); does a similar thing to
# while(Win32::GUI::DoEvents() != -1) {};
#
# See also DoEvents()
# See also DoModal()
WPARAM
Dialog(hwnd=NULL)
HWND hwnd
PREINIT:
MSG msg;
HWND phwnd;
HWND thwnd;
int stayhere;
BOOL fIsDialog;
BOOL fIsMDI;
HACCEL acc;
LPPERLWIN32GUI_USERDATA perlud;
LPPERLWIN32GUI_USERDATA tperlud;
CODE:
stayhere = 1;
fIsDialog = FALSE;
while (stayhere) {
ENTER;
SAVETMPS;
stayhere = GetMessage(&msg, hwnd, 0, 0);
if(msg.message == WM_EXITLOOP) {
stayhere = 0;
msg.wParam = (WPARAM) -1;
} else if(stayhere == -1) {
stayhere = 0;
msg.wParam = (WPARAM) -2; // an error occurred...
} else {
// #### trace back to the window's parent
phwnd = msg.hwnd;
while((thwnd = GetParent(phwnd)) && IsChild(thwnd, phwnd) ) {
phwnd = thwnd;
}
// #### now see if the parent window is a DialogBox
fIsDialog = fIsMDI = FALSE;
acc = NULL;
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(phwnd, GWLP_USERDATA);
if( ValidUserData(perlud) ) {
fIsDialog = perlud->dwPlStyle & PERLWIN32GUI_DIALOGUI;
fIsMDI = perlud->dwPlStyle & (PERLWIN32GUI_MDIFRAME | PERLWIN32GUI_HAVECHILDWINDOW);
acc = perlud->hAcc;
}
// ### If the parent window is a MDIFrame the active MDIChild
// ### can be THE DialogBox
if(fIsMDI
&& (thwnd = (HWND)SendMessage(INT2PTR(HWND, perlud->dwData), WM_MDIGETACTIVE, (WPARAM) 0, (LPARAM) NULL))
&& (tperlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(thwnd, GWLP_USERDATA))
&& ValidUserData(tperlud))
{
fIsDialog = tperlud->dwPlStyle & PERLWIN32GUI_DIALOGUI;
}
else {
thwnd = phwnd;
}
if( !( (fIsMDI && TranslateMDISysAccel(INT2PTR(HWND, perlud->dwData), &msg)) ||
(acc && TranslateAccelerator(phwnd, acc, &msg)) ||
(fIsDialog && IsDialogMessage(thwnd, &msg)) )
){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
FREETMPS;
LEAVE;
}
RETVAL = msg.wParam;
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:DoEvents(hwnd=NULL,wMsgFilterMin=0,wMsgFilterMax=0,wRemoveMsg=PM_REMOVE)
# Performs all pending GUI events and returns the status. If DoEvents()
# returns -1, your GUI has normally terminated.
#
# You can call $window->DoEvents() to process pending events relating to a
# specific window, or Win32::GUI::DoEvents() to process pending events for all
# windows.
#
# see also Dialog()
WPARAM
DoEvents(hwnd=NULL,wMsgFilterMin=0,wMsgFilterMax=0,wRemoveMsg=PM_REMOVE)
HWND hwnd
UINT wMsgFilterMin
UINT wMsgFilterMax
UINT wRemoveMsg
PREINIT:
MSG msg;
HWND phwnd;
HWND thwnd;
int stayhere;
BOOL fIsDialog;
BOOL fIsMDI;
HACCEL acc;
LPPERLWIN32GUI_USERDATA perlud;
LPPERLWIN32GUI_USERDATA tperlud;
CODE:
stayhere = 1;
fIsDialog = FALSE;
while(stayhere) {
stayhere = PeekMessage(&msg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
#ifdef PERLWIN32GUI_STRONGDEBUG
printf("XS(DoEvents): PeekMessage returned %d\n", stayhere);
#endif
if (stayhere) {
if(msg.message == WM_EXITLOOP) {
stayhere = 0;
msg.wParam = (WPARAM) -1;
} else {
// #### trace back to the window's parent
phwnd = msg.hwnd;
while((thwnd = GetParent(phwnd)) && IsChild(thwnd, phwnd) ) {
phwnd = thwnd;
}
// #### now see if the parent window is a DialogBox
fIsDialog = fIsMDI = FALSE;
acc = NULL;
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(phwnd, GWLP_USERDATA);
if( ValidUserData(perlud) ) {
fIsDialog = perlud->dwPlStyle & PERLWIN32GUI_DIALOGUI;
fIsMDI = perlud->dwPlStyle & (PERLWIN32GUI_MDIFRAME | PERLWIN32GUI_HAVECHILDWINDOW);
acc = perlud->hAcc;
}
// ### If the parent window is a MDIFrame the active MDIChild
// ### can be THE DialogBox
if(fIsMDI
&& (thwnd = (HWND)SendMessage(INT2PTR(HWND, perlud->dwData), WM_MDIGETACTIVE, (WPARAM) 0, (LPARAM) NULL))
&& (tperlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(thwnd, GWLP_USERDATA))
&& ValidUserData(tperlud))
{
fIsDialog = tperlud->dwPlStyle & PERLWIN32GUI_DIALOGUI;
}
else {
thwnd = phwnd;
}
if( !( (fIsMDI && TranslateMDISysAccel(INT2PTR(HWND, perlud->dwData), &msg)) ||
(acc && TranslateAccelerator(phwnd, acc, &msg)) ||
(fIsDialog && IsDialogMessage(thwnd, &msg)) )
){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
else
msg.wParam = (WPARAM) 0;
}
RETVAL = msg.wParam;
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:DoModal([DISABLE_ALL=FALSE])
# Enter the GUI dialog phase for a specific window: the script halts, the
# user can interact with the window, events subroutines are triggered as
# necessary, but no other windows in the application will accept input.
# DoModal() also brings the window on top of all other windows.
#
# B<DISABLE_ALL> flag can set for deactivate all top window and not only parent/active window.
#
# The correct usage is:
# $window->DoModal(1);
#
# To exit from the GUI dialog phase of the modal window, return -1 from the event handler.
#
# See also Dialog()
# See also DoEvents()
WPARAM
DoModal(handle, all=FALSE)
HWND handle
BOOL all
PREINIT:
LPPERLWIN32GUI_USERDATA perlud;
MSG msg;
int stayhere;
HWND phwnd;
HWND thwnd;
BOOL fIsDialog;
BOOL fIsMDI;
HACCEL acc;
HWND parent;
CODE:
// Set ISMODAL flag
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(handle, GWLP_USERDATA);
if( !ValidUserData(perlud) || (perlud->dwPlStyle & PERLWIN32GUI_ISMODAL) )
XSRETURN_NO;
perlud->dwPlStyle |= PERLWIN32GUI_ISMODAL;
// Find its owner window if any or use ActiveWindow
parent = GetWindow(handle, GW_OWNER);
if (parent == NULL) {
parent = GetActiveWindow();
}
// Disable parent window or all top window
if (all)
EnumThreadWindows (GetWindowThreadProcessId(parent, NULL), (WNDENUMPROC) EnableWindowsProc, (LPARAM) FALSE);
else
EnableWindow (parent, FALSE);
// Enable/Show Dialog
EnableWindow (handle, TRUE);
ShowWindow(handle, SW_SHOWNORMAL);
SetActiveWindow(handle);
// Go to message loop
stayhere = 1;
while (stayhere) {
ENTER;
SAVETMPS;
stayhere = GetMessage(&msg, NULL, 0, 0);
if(msg.message == WM_EXITLOOP || msg.message == WM_QUIT) {
stayhere = 0;
msg.wParam = (WPARAM) 0; // Don't return -1 for a DoModal
} else if(stayhere == -1) {
stayhere = 0;
msg.wParam = (WPARAM) -1; // an error occurred...
} else {
// #### trace back to the window's parent
phwnd = msg.hwnd;
while((thwnd = GetParent(phwnd)) && IsChild(thwnd, phwnd) ) {
phwnd = thwnd;
}
// #### now see if the parent window is a DialogBox
fIsDialog = fIsMDI = FALSE;
acc = NULL;
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(phwnd, GWLP_USERDATA);
if( ValidUserData(perlud) ) {
fIsDialog = perlud->dwPlStyle & PERLWIN32GUI_DIALOGUI;
fIsMDI = perlud->dwPlStyle & (PERLWIN32GUI_MDIFRAME | PERLWIN32GUI_HAVECHILDWINDOW);
acc = perlud->hAcc;
}
if( !( (fIsMDI && TranslateMDISysAccel(INT2PTR(HWND, perlud->dwData), &msg)) ||
(acc && TranslateAccelerator(phwnd, acc, &msg)) ||
(fIsDialog && IsDialogMessage(phwnd, &msg)) )
){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
FREETMPS;
LEAVE;
}
// Enable parent or all active topwindow
if (all)
EnumThreadWindows (GetWindowThreadProcessId(parent, NULL), (WNDENUMPROC) EnableWindowsProc, (LPARAM) TRUE);
else
EnableWindow (parent, TRUE);
// Hide DialogBox
ShowWindow(handle, SW_HIDE);
// Active parent
SetActiveWindow(parent);
// UnSet ISMODAL flag
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(handle, GWLP_USERDATA);
if( ValidUserData(perlud))
perlud->dwPlStyle &= ~PERLWIN32GUI_ISMODAL;
RETVAL = msg.wParam;
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Scroll(scrollbar,operation[,position, [thumbtrack_flag]])
# Handles scrollbar scrolling if you don't want to do it yourself. This is
# most useful in the Scroll event handler for a window or dialog box.
#
# B<scrollbar> can be:
# SB_HOR(0) : Horizontal scrollbar
# SB_VERT(1) : Vertical scrollbar
#
# B<operation> is an identifier for the operation being performed on the
# scrollbar, this can be:
# SB_LINEUP, SB_LINELEFT, SB_LINEDOWN, SB_LINERIGHT, SB_PAGEUP
# SB_PAGELEFT, SB_PAGEDOWN, SB_PAGERIGHT, SB_THUMBPOSITION,
# SB_THUMBTRACK, SB_TOP, SB_LEFT, SB_BOTTOM, SB_RIGHT, or SB_ENDSCROLL
#
# B<position> is ignored unless B<operation> is SB_THUMBPOSITION, or
# B<operation> is SB_THUMBTRACK and B<thumbtrack_flag> is TRUE. If
# B<position> is not provided (or provided and equal to -1), then
# the position used is taken from the internal scrollbar structure:
# this is the prefered method of operation.
#
# B<thumbtrack_flag> indicates whether SB_THUMBTRACK messages are
# processed (TRUE) or not (FALSE). It defaults to false.
#
# Returns the new position of the scrollbar, or undef on failure.
#
int
Scroll(handle, scrollbar, operation, position = -1, thumbtrack_flag = 0)
HWND handle
int scrollbar
int operation
int position
BOOL thumbtrack_flag
PREINIT:
SCROLLINFO si;
CODE:
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
if(GetScrollInfo(handle,scrollbar,&si)) {
si.fMask = SIF_POS;
switch(operation) {
case SB_THUMBTRACK:
if(!thumbtrack_flag) {
/* No tracking */
break;
}
/* fall through */
case SB_THUMBPOSITION:
if(position == -1) {
si.nPos = si.nTrackPos;
}
else {
si.nPos = position;
}
break;
case SB_LINEUP:
si.nPos--;
break;
case SB_LINEDOWN:
si.nPos++;
break;
case SB_PAGEUP:
si.nPos -= si.nPage;
break;
case SB_PAGEDOWN:
si.nPos += si.nPage;
break;
case SB_TOP:
si.nPos = si.nMin;
break;
case SB_BOTTOM:
si.nPos = si.nMax;
break;
default:
XSRETURN_UNDEF;
break;
}
RETVAL = SetScrollInfo(handle, scrollbar, &si, 1);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ScrollRange(scrollbar,[min, max])
# Sets / Gets range for a window scrollbar (if enabled).
# B<scrollbar> argument should be set as follows:
# 0 : Horizontal scrollbar
# 1 : Vertical scrollbar
#
# Returns the scrollbar range as an array, or undef on failure.
void
ScrollRange(handle, scrollbar,...)
HWND handle
int scrollbar
PREINIT:
SCROLLINFO si; // We use scrollinfo because SetScrollRange is deprecated.
CODE:
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_RANGE;
if(scrollbar > 1) XSRETURN_UNDEF;
if(items > 2) {
si.nMin = (int)SvIV(ST(2));
si.nMax = (int)SvIV(ST(3));
SetScrollInfo(handle, scrollbar, &si, 1);
}
if(GetScrollInfo(handle,scrollbar,&si)) {
EXTEND(SP, 2);
XST_mIV(0, si.nMin);
XST_mIV(1, si.nMax);
XSRETURN(2);
}
else {
XSRETURN_UNDEF;
}
###########################################################################
# (@)METHOD:ScrollPage(scrollbar,[pagesize])
# Sets / Gets page size of a window scrollbar (if enabled).
# B<scrollbar> argument should be set as follows:
# 0 : Horizontal scrollbar
# 1 : Vertical scrollbar
#
# Returns the scrollbar page size or undef on failure.
DWORD
ScrollPage(handle, scrollbar,...)
HWND handle
int scrollbar
PREINIT:
SCROLLINFO si;
CODE:
si.cbSize = sizeof(SCROLLINFO);
if(scrollbar > 1) XSRETURN_UNDEF;
si.fMask = SIF_PAGE;
if(items > 2) {
si.nPage = (UINT)SvIV(ST(2));
SetScrollInfo(handle, scrollbar, &si, 1);
}
if(GetScrollInfo(handle,scrollbar,&si)) {
RETVAL = si.nPage;
}
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ScrollPos(scrollbar,[pos])
# Sets / Gets position of a window scrollbar (if enabled).
# B<scrollbar> argument should be set as follows:
# 0 : Horizontal scrollbar
# 1 : Vertical scrollbar
#
# Returns the scrollbar position or undef on failure.
DWORD
ScrollPos(handle, scrollbar,...)
HWND handle
int scrollbar
PREINIT:
SCROLLINFO si;
CODE:
si.cbSize = sizeof(SCROLLINFO);
if(scrollbar > 1) XSRETURN_UNDEF;
if(items > 2) {
si.fMask = SIF_POS;
si.nPos = (int)SvIV(ST(2));
SetScrollInfo(handle, scrollbar, &si, 1);
}
si.fMask = SIF_POS;
if(GetScrollInfo(handle,scrollbar,&si)) {
RETVAL = si.nPos;
}
OUTPUT:
RETVAL
###########################################################################
# (@)INTERNAL:LoadCursorFromFile(FILENAME)
HCURSOR
LoadCursorFromFile(filename)
LPCTSTR filename
CODE:
RETVAL = LoadCursorFromFile(filename);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:LoadCursor(ID)
#This function loads one of the default cursors. ID can be one of:
#
# 32650 IDC_APPSTARTING Standard arrow and small hourglass
# 32512 IDC_ARROW Standard arrow
# 32515 IDC_CROSS Crosshair
# 32649 IDC_HAND Windows 98/Me, Windows 2000/XP: Hand
# 32651 IDC_HELP Arrow and question mark
# 32513 IDC_IBEAM I-beam
# 32641 IDC_ICON Obsolete for applications marked version 4.0 or later.
# 32648 IDC_NO Slashed circle
# 32640 IDC_SIZE Obsolete for applications marked version 4.0 or later. Use IDC_SIZEALL.
# 32646 IDC_SIZEALL Four-pointed arrow pointing north, south, east, and west
# 32643 IDC_SIZENESW Double-pointed arrow pointing northeast and southwest
# 32645 IDC_SIZENS Double-pointed arrow pointing north and south
# 32642 IDC_SIZENWSE Double-pointed arrow pointing northwest and southeast
# 32644 IDC_SIZEWE Double-pointed arrow pointing west and east
# 32516 IDC_UPARROW Vertical arrow
# 32514 IDC_WAIT Hourglass
#
#On success returns a Win32::GUI::Cursor object, on failure undef.
#
#Example:
#
#my $hourglass=Win32::GUI::LoadCursor(32514);
#
#NOTE: it is better to use Win32::GUI::Cursor->new(ID);
void
LoadCursor(ID)
long ID
PREINIT:
HCURSOR cursor;
PPCODE:
cursor = LoadCursor(NULL, MAKEINTRESOURCE(ID));
if (cursor== NULL) XSRETURN_UNDEF;
XPUSHs(CreateObjectWithHandle(NOTXSCALL "Win32::GUI::Cursor", (HWND) cursor));
##########################################################################
# (@)METHOD:LoadString(ID)
# The LoadString method loads a string resource from the executable file
LPTSTR
LoadString(uID)
UINT uID
PREINIT:
char lpBuffer[256];
HINSTANCE moduleHandle;
CODE:
moduleHandle = GetModuleHandle(NULL);
if(LoadString(moduleHandle,uID,lpBuffer,256)) {
RETVAL = (LPTSTR) lpBuffer;
} else {
RETVAL = "";
}
OUTPUT:
RETVAL
###########################################################################
# (@)INTERNAL:LoadImage(FILENAME, [TYPE, X, Y, FLAGS])
# The return value is a handle to the bitmap, or 0 on failure.
#
# Directory seperators are normalised to windows seperators (C<\>).
# Under Cygwin, cygwin paths are converted to windows paths
HBITMAP
LoadImage(filename,iType=IMAGE_BITMAP,iX=0,iY=0,iFlags=LR_DEFAULTCOLOR)
SV *filename
UINT iType
int iX
int iY
UINT iFlags
PREINIT:
HINSTANCE moduleHandle;
HBITMAP bitmap = NULL;
char buffer[MAX_PATH+1];
char *name;
int i;
CODE:
/* Try to find the resource in the current EXE */
moduleHandle = GetModuleHandle(NULL);
/* If filename looks like a string, attempt to load from current EXE: */
if((bitmap ==NULL) && SvPOK(filename) && !(iFlags & LR_LOADFROMFILE)) {
bitmap = (HBITMAP) LoadImage((HINSTANCE) moduleHandle,
SvPV_nolen(filename), iType, iX, iY, iFlags);
}
/* If filename looks like a number, try it as a resource id from the current EXE */
if((bitmap == NULL) && SvIOK(filename) && !(iFlags & LR_LOADFROMFILE)) {
bitmap = (HBITMAP) LoadImage((HINSTANCE) moduleHandle,
MAKEINTRESOURCE(SvIV(filename)), iType, iX, iY, iFlags);
}
/* Try to find the resource from GUI.dll */
moduleHandle = GetModuleHandle("GUI.dll");
/* If filename looks like a string, try it as a resource name from GUI.dll */
if((bitmap == NULL) && SvPOK(filename) && !(iFlags & LR_LOADFROMFILE)) {
bitmap = (HBITMAP) LoadImage((HINSTANCE) moduleHandle,
SvPV_nolen(filename), iType, iX, iY, iFlags);
}
/* If filename looks like a number, try it as a resource id from GUI.dll */
if((bitmap == NULL) && SvIOK(filename) && !(iFlags & LR_LOADFROMFILE)) {
bitmap = (HBITMAP) LoadImage((HINSTANCE) moduleHandle,
MAKEINTRESOURCE(SvIV(filename)), iType, iX, iY, iFlags);
}
/* Try to load from file or as an OEM resource */
moduleHandle = NULL;
/* if filename looks like a string, try it as a file name */
if((bitmap == NULL) && SvPOK(filename)) {
name = SvPV_nolen(filename);
#ifdef __CYGWIN__
/* Under Cygwin, convert paths to windows
* paths. E.g. convert /usr/local... and /cygdrive/c/...
*/
#if CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR >= 181
i = cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE,name,buffer,MAX_PATH+1);
if (i < 0) XSRETURN_UNDEF;
#else
/* old cygwin api */
if(cygwin_conv_to_win32_path(name,buffer) != 0)
XSRETURN_UNDEF;
#endif
#else
/* LoadImage on Win98 (at least) doesn't like unix
* path seperators, so normalise to windows path seperators
*/
for(i=0; *name && (i<MAX_PATH); ++name,++i) {
buffer[i] = (*name == '/' ? '\\' : *name);
}
if(*name) {
/* XXX Path too long - although this appears to be what
* LoadImage would return with such a path, it might be
* better to find a more specific error code. E.g.
* ENAMETOOLONG?
*/
SetLastError(ERROR_FILE_NOT_FOUND);
errno = ENOENT;
XSRETURN_UNDEF;
}
buffer[i] = 0;
#endif
bitmap = (HBITMAP) LoadImage((HINSTANCE) moduleHandle,
buffer, iType, iX, iY, iFlags|LR_LOADFROMFILE);
}
/* If filename looks like a number, try it as an OEM resource id */
if((bitmap == NULL) && SvIOK(filename) && !(iFlags & LR_LOADFROMFILE)) {
bitmap = (HBITMAP) LoadImage((HINSTANCE) moduleHandle,
MAKEINTRESOURCE(SvIV(filename)), iType, iX, iY, iFlags);
}
/* Finally, if it looks like a number, try it as a pre-defined resource */
if((bitmap == NULL) && SvIOK(filename)) {
if(iType == IMAGE_BITMAP) {
bitmap = (HBITMAP)LoadBitmap(NULL, MAKEINTRESOURCE(SvIV(filename)));
}
else if (iType == IMAGE_ICON) {
bitmap = (HBITMAP)LoadIcon(NULL, MAKEINTRESOURCE(SvIV(filename)));
}
else if (iType == IMAGE_CURSOR) {
bitmap = (HBITMAP)LoadCursor(NULL, MAKEINTRESOURCE(SvIV(filename)));
}
}
RETVAL = bitmap;
OUTPUT:
RETVAL
###########################################################################
# (@)INTERNAL:DestroyCursor()
BOOL
DestroyCursor(cursor)
HCURSOR cursor
CODE:
RETVAL = DestroyCursor(cursor);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:SetCursor(CURSOR)
# Draws the specified B<CURSOR> (a Win32::GUI::Cursor object). Returns the
# handle of the previously displayed cursor. Note that the cursor will
# change back to the default one as soon as the mouse moves or a system
# command is performed. To change the cursor stablily, use ChangeCursor().
#
# see also ChangeCursor()
HCURSOR
SetCursor(cursor)
HCURSOR cursor
CODE:
RETVAL = SetCursor(cursor);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetCursor()
# Returns the handle of the current cursor.
HCURSOR
GetCursor()
CODE:
RETVAL = GetCursor();
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ChangeCursor(CURSOR)
# Changes the default cursor for a window to B<CURSOR> (a Win32::GUI::Cursor
# object). Returns the handle of the previous default cursor.
#
# see also new Win32::GUI::Cursor
HCURSOR
ChangeCursor(handle, cursor)
HWND handle
HCURSOR cursor
CODE:
RETVAL = (HCURSOR) SetClassLongPtr(handle, GCLP_HCURSOR, (LONG_PTR) cursor);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetCursorPos()
# Gets the absolute mouse cursor position. Returns an array containing
# x and y co-ordinates.
#
# Usage:
# ($x, $y) = Win32::GUI::GetCursorPos;
#
# See also ScreenToClient()
# See also SetCursorPos()
void
GetCursorPos()
PREINIT:
POINT point;
PPCODE:
if(GetCursorPos(&point)) {
EXTEND(SP, 2);
XST_mIV(0, point.x);
XST_mIV(1, point.y);
XSRETURN(2);
} else {
XSRETURN_UNDEF;
}
###########################################################################
# (@)METHOD:SetCursorPos(X, Y)
# Moves the mouse cursor to the specified screen coordinates.
#
# see also GetCursorPos()
BOOL
SetCursorPos(x, y)
int x
int y
CODE:
RETVAL = SetCursorPos(x, y);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ClipCursor([LEFT, TOP, RIGHT, BOTTOM])
# Confines the cursor to the specified screen rectangle. Call it without
# parameters to release the cursor. Returns nonzero on success
BOOL
ClipCursor(left=0, top=0, right=0, bottom=0)
LONG left
LONG top
LONG right
LONG bottom
PREINIT:
RECT r;
CODE:
if(items == 0) {
RETVAL = ClipCursor(NULL);
} else {
r.left = left;
r.top = top;
r.right = right;
r.bottom = bottom;
RETVAL = ClipCursor(&r);
}
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ChangeIcon(ICON)
# Changes the default icon for a window to B<ICON> (a Win32::GUI::Icon
# object). Returns the handle of the previous default icon.
HICON
ChangeIcon(handle, icon)
HWND handle
HICON icon
CODE:
SetClassLongPtr(handle, GCLP_HICONSM, (LONG_PTR) icon);
RETVAL = (HICON) SetClassLongPtr(handle, GCLP_HICON, (LONG_PTR) icon);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ChangeSmallIcon(ICON)
# Changes the default small icon for a window to B<ICON> (a Win32::GUI::Icon
# object). Returns the handle of the previous default small icon.
HICON
ChangeSmallIcon(handle, icon)
HWND handle
HICON icon
CODE:
RETVAL = (HICON) SetClassLongPtr(handle, GCLP_HICONSM, (LONG_PTR) icon);
OUTPUT:
RETVAL
###########################################################################
# (@)INTERNAL:DestroyIcon()
BOOL
DestroyIcon(icon)
HICON icon
CODE:
RETVAL = DestroyIcon(icon);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetClassName()
# Returns the class name for a window or control.
void
GetClassName(handle)
HWND handle
PREINIT:
LPTSTR lpClassName;
int nMaxCount;
PPCODE:
nMaxCount = 256;
lpClassName = (LPTSTR) safemalloc(nMaxCount);
if(GetClassName(handle, lpClassName, nMaxCount) > 0) {
EXTEND(SP, 1);
XST_mPV(0, lpClassName);
safefree(lpClassName);
XSRETURN(1);
} else {
safefree(lpClassName);
XSRETURN_NO;
}
###########################################################################
# (@)METHOD:GetParent()
# Returns the parent window for this child control/window. If there is no
# parent window or there has been an error, undef is returned.
void
GetParent(handle)
HWND handle
PREINIT:
HWND parentHandle;
SV* SvParent;
PPCODE:
parentHandle=GetParent(handle);
if (parentHandle!=NULL) {
SvParent = SV_SELF_FROM_WINDOW(parentHandle);
if (SvParent != NULL && SvROK(SvParent)) {
XPUSHs(SvParent);
}
else {
XSRETURN_UNDEF;
}
}
else {
XSRETURN_UNDEF;
}
###########################################################################
# (@)INTERNAL:GetWindowObject()
# Returns the perl window object from a window handle. If the window handle
# passed is a handle to a window created by Win32::GUI, returns the perl
# object reference, else returns undef.
void
GetWindowObject(handle)
HWND handle
PREINIT:
SV* SvObject;
PPCODE:
if (IsWindow(handle)) {
SvObject = SV_SELF_FROM_WINDOW(handle);
if (SvObject != NULL && SvROK(SvObject)) {
XPUSHs(SvObject);
}
else {
XSRETURN_UNDEF;
}
}
else {
XSRETURN_UNDEF;
}
###########################################################################
# (@)INTERNAL:_UserData()
# Return a reference to an HV, stored in the perlud.userData member
# of the PERLWIN32GUI_USERDATA struct
HV *
_UserData(handle)
HWND handle
PREINIT:
LPPERLWIN32GUI_USERDATA perlud;
CODE:
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(handle, GWLP_USERDATA);
if( ! ValidUserData(perlud) ) {
XSRETURN_UNDEF;
}
if(perlud->userData == NULL)
perlud->userData = (SV*)newHV();
RETVAL = (HV*)perlud->userData;
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:FindWindow(CLASSNAME, WINDOWNAME)
# Returns the handle of the window whose class name and window name match
# the specified strings; both strings can be empty. Note that the function
# does not search child windows, only top level windows.
#
# If no matching windows is found, the return value is zero.
HWND
FindWindow(classname,windowname)
LPCTSTR classname
LPCTSTR windowname
CODE:
if(strlen(classname) == 0) classname = NULL;
if(strlen(windowname) == 0) windowname = NULL;
RETVAL = FindWindow(classname, windowname);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetWindowLong(INDEX)
# Retrieves a windows property; for more info consult the original API
# documentation.
void
GetWindowLong(handle,index)
HWND handle
int index
PPCODE:
XSRETURN_IV(PTR2IV(GetWindowLongPtr(handle, index)));
###########################################################################
# (@)METHOD:SetWindowLong(INDEX, VALUE)
# Sets a windows property; for more info consult the original API
# documentation.
void
SetWindowLong(handle,index,value)
HWND handle
int index
LONG_PTR value
PPCODE:
XSRETURN_IV(PTR2IV(SetWindowLongPtr(handle, index, value)));
###########################################################################
# (@)METHOD:SetWindowPos(INSERTAFTER,X,Y,cx,cy,FLAGS)
# The SetWindowPos function changes the size, position,
# and Z order of a child, pop-up, or top-level
# window. Child, pop-up, and top-level windows are
# ordered according to their appearance on the
# screen. The topmost window receives the highest rank
# and is the first window in the Z order.
#
# INSERTAFTER - window to precede the positioned window
# in the Z order. This parameter must be a window object,
# a window handle or one of the following integer values.
# HWND_BOTTOM
# Places the window at the bottom of the Z order. If
# the WINDOW parameter identifies a topmost window,
# the window loses its topmost status and is placed
# at the bottom of all other windows.
# HWND_NOTOPMOST
# Places the window above all non-topmost windows
# (that is, behind all topmost windows). This flag
# has no effect if the window is already a
# non-topmost window.
# HWND_TOP
# Places the window at the top of the Z order.
# HWND_TOPMOST
# Places the window above all non-topmost
# windows. The window maintains its topmost position
# even when it is deactivated.
BOOL
SetWindowPos(handle,insertafter,X,Y,cx,cy,flags)
HWND handle
HWND insertafter
int X
int Y
int cx
int cy
int flags
CODE:
RETVAL = SetWindowPos(handle, insertafter, X, Y, cx, cy, flags);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetWindow(COMMAND)
# Returns handle of the window that has the specified
# relationship (given by B<COMMAND>) with the specified window.
#
# Available B<COMMAND> are:
# GW_CHILD
# GW_HWNDFIRST
# GW_HWNDLAST
# GW_HWNDNEXT
# GW_HWNDPREV
# GW_OWNER
#
# Example:
# $Button->GetWindow(GW_OWNER);
HWND
GetWindow(handle,command)
HWND handle
UINT command
CODE:
RETVAL = GetWindow(handle, command);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Show([COMMAND=SW_SHOWNORMAL])
# Shows a window (or change its showing state to B<COMMAND>);
#
# Available B<COMMAND> are:
#
# 0 : SW_HIDE
# 1 : SW_SHOWNORMAL
# 1 : SW_NORMAL
# 2 : SW_SHOWMINIMIZED
# 3 : SW_SHOWMAXIMIZED
# 3 : SW_MAXIMIZE
# 4 : SW_SHOWNOACTIVATE
# 5 : SW_SHOW
# 6 : SW_MINIMIZE
# 7 : SW_SHOWMINNOACTIVE
# 8 : SW_SHOWNA
# 9 : SW_RESTORE
# 10 : SW_SHOWDEFAULT
# 11 : SW_FORCEMINIMIZE
# 11 : SW_MAX
#
BOOL
Show(handle,command=SW_SHOWNORMAL)
HWND handle
int command
CODE:
RETVAL = ShowWindow(handle, command);
OUTPUT:
RETVAL
###########################################################################
# (@)INTERNAL:_Animate(HANDLE, TIME, FLAGS)
# Wrapper for Win32 AnimateWindow call. See Win32::GUI::Animate in GUI.pm
# for more details.
BOOL
_Animate(handle, time, flags)
HWND handle
DWORD time
DWORD flags
CODE:
RETVAL = AnimateWindow(handle, time, flags);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Hide()
# Hides a window or control.
BOOL
Hide(handle)
HWND handle
CODE:
RETVAL = ShowWindow(handle, SW_HIDE);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Maximize()
# Maximizes a window.
BOOL
Maximize(handle)
HWND handle
CODE:
RETVAL = ShowWindow(handle, SW_SHOWMAXIMIZED);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:SetWindowRgn(region,flag)
# The SetWindowRgn method sets the window region of a window. The window region determines the area
# within the window where the system permits drawing. The system does not display any portion of a window
# that lies outside of the window region
#
# flag : Specifies whether the system redraws the window after setting the window region. If flag is TRUE,
# the system does so; otherwise, it does not.
# Typically, you set flag to TRUE if the window is visible.
BOOL
SetWindowRgn(handle, region, flag=1)
HWND handle
HRGN region
BOOL flag
CODE:
RETVAL = SetWindowRgn(handle, region, flag);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Update()
# Repaints a window if it's update region is not empty.
#
# see also Redraw()
# see also InvalidateRect()
BOOL
Update(handle)
HWND handle
CODE:
RETVAL = UpdateWindow(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Redraw()
# Repaints a window
#
# See also Update()
# See also InvalidateRect()
BOOL
Redraw(handle, ...)
HWND handle
PREINIT:
RECT rect;
LPRECT lpRect;
UINT flags;
CODE:
if(items != 2 && items != 6) {
CROAK("Usage: Redraw(handle, flag);\n or: Redraw(handle, left, top, right, bottom, flag);\n");
}
if(items == 2) {
lpRect = (LPRECT) NULL;
flags = (UINT) SvIV(ST(1));
}
else {
rect.left = (LONG)SvIV(ST(1));
rect.top = (LONG)SvIV(ST(2));
rect.right = (LONG)SvIV(ST(3));
rect.bottom = (LONG)SvIV(ST(4));
flags = (UINT) SvIV(ST(5));
lpRect = &rect;
}
RETVAL = RedrawWindow(handle,lpRect, (HRGN) NULL, flags);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:LockWindowUpdate(flag)
# The LockWindowUpdate method disables or enables drawing in the specified window. Only one window
# can be locked at a time.
#
# If an application with a locked window (or any locked child windows) calls the GetDC function,
# the called function returns a device context with a visible region that is empty. This will
# occur until the application unlocks the window by calling LockWindowUpdate method specifying a
# value for the flag.
# Example:
# $win->LockWindowUpdate; #Locks window
# $win->LockWindowUpdate(1); #Unlocks window
BOOL
LockWindowUpdate(handle, flag=0)
HWND handle
int flag
CODE:
RETVAL = LockWindowUpdate(flag == 0 ? handle : NULL);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:InvalidateRect(...)
# Forces a refresh of a window, or a rectangle of it.
#
# The parameters can be B<(FLAG)> for the whole area of the window, or B<(LEFT, TOP, RIGHT, BOTTOM,
# [FLAG])> to specify a rectangle. If the B<FLAG> parameter is set to TRUE, the
# background is erased before the window is refreshed (this is the default).
#
# See also Redraw()
# See also Update()
BOOL
InvalidateRect(handle, ...)
HWND handle
PREINIT:
RECT rect;
LPRECT lpRect;
BOOL bErase;
CODE:
if(items != 2 && items && items != 6) {
CROAK("Usage: InvalidateRect(handle, flag);\n or: InvalidateRect(handle, left, top, right, bottom, [flag]);\n");
}
if(items == 2) {
lpRect = (LPRECT) NULL;
bErase = (BOOL) SvIV(ST(1));
} else {
rect.left = (LONG)SvIV(ST(1));
rect.top = (LONG)SvIV(ST(2));
rect.right = (LONG)SvIV(ST(3));
rect.bottom = (LONG)SvIV(ST(4));
if(items == 5)
bErase = TRUE;
else
bErase = (BOOL) SvIV(ST(5));
lpRect = &rect;
}
RETVAL = InvalidateRect(handle, lpRect, bErase);
OUTPUT:
RETVAL
###########################################################################
# (@)INTERNAL:DestroyWindow()
BOOL
DestroyWindow(handle)
HWND handle
CODE:
RETVAL = DestroyWindow(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetMessage([MIN=0, MAX=0])
# Retrieves a message sent to the window, optionally considering only
# messages identifiers in the range B<MIN..MAX>.
#
# If a message is found, the function returns a 7 elements array containing:
#
# - the result code of the message
# - the message identifier
# - the wParam argument
# - the lParam argument
# - the time when message occurred
# - the x coordinate at which message occurred
# - the y coordinate at which message occurred
#
# If the result code of the message was -1 the function returns undef. Note
# that this function should not be normally used unless you know very well
# what you're doing.
void
GetMessage(handle,min=0,max=0)
HWND handle
UINT min
UINT max
PREINIT:
MSG msg;
BOOL result;
PPCODE:
result = GetMessage(&msg, handle, min, max);
if(result == -1) {
XSRETURN_UNDEF;
} else {
EXTEND(SP, 7);
XST_mIV(0, result);
XST_mIV(1, msg.message);
XST_mIV(2, msg.wParam);
XST_mIV(3, msg.lParam);
XST_mIV(4, msg.time);
XST_mIV(5, msg.pt.x);
XST_mIV(6, msg.pt.y);
XSRETURN(7);
}
###########################################################################
# (@)METHOD:SendMessage(MSG, WPARAM, LPARAM)
# Sends a message to a window.
LRESULT
SendMessage(handle,msg,wparam,lparam)
HWND handle
UINT msg
WPARAM wparam
LPARAM lparam
CODE:
RETVAL = SendMessage(handle, msg, wparam, lparam);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:PostMessage(MSG, WPARAM, LPARAM)
# Posts a message to a window.
LRESULT
PostMessage(handle,msg,wparam,lparam)
HWND handle
UINT msg
WPARAM wparam
LPARAM lparam
CODE:
RETVAL = PostMessage(handle, msg, wparam, lparam);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:WaitMessage()
# The WaitMessage function yields control to other threads when a thread
# has no other messages in its message queue. The WaitMessage function suspends
# the thread and does not return until a new message is placed in the thread's
# message queue.
BOOL
WaitMessage()
CODE:
RETVAL = WaitMessage();
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:SendMessageTimeout(MSG, WPARAM, LPARAM, [FLAGS=SMTO_NORMAL], TIMEOUT)
# Sends a message to a window and wait for it to be processed or until the
# specified B<TIMEOUT> (number of milliseconds) elapses.
#
# Returns the result code of the processed message or undef on errors.
#
# If undef is returned and a call to Win32::GetLastError() returns 0,
# then the window timed out processing the message.
#
# The B<FLAGS> parameter is optional, possible values are:
# 0 : SMTO_NORMAL
# The calling thread can process other requests while waiting; this is the default setting.
# 1 : SMTO_BLOCK
# The calling thread does not process other requests.
# 2 : SMTO_ABORTIFHUNG
# Returns without waiting if the receiving process seems to be "hung".
void
SendMessageTimeout(handle,msg,wparam,lparam,flags=SMTO_NORMAL,timeout)
HWND handle
UINT msg
WPARAM wparam
LPARAM lparam
UINT flags
UINT timeout
PREINIT:
PDWORD result;
PPCODE:
if(SendMessageTimeout(handle, msg, wparam, lparam, flags, timeout, (PDWORD_PTR)&result) == 0) {
XSRETURN_UNDEF;
} else {
XSRETURN_IV((IV)result);
}
###########################################################################
# (@)METHOD:PostQuitMessage([EXITCODE])
# Sends a quit message to a window, optionally with an B<EXITCODE>;
# if no B<EXITCODE> is given, it defaults to 0.
void
PostQuitMessage(...)
PPCODE:
int exitcode;
if(items > 0)
exitcode = (int)SvIV(ST(items-1));
else
exitcode = 0;
PostQuitMessage(exitcode);
###########################################################################
# (@)METHOD:PeekMessage([MIN, MAX, MESSAGE])
# Inspects the window's message queue and eventually returns data
# about the message it contains; it can optionally check only for message
# identifiers in the range B<MIN..MAX>; the last B<MESSAGE parameter>, if
# specified, must be an array reference.
#
# If a message is found, the function puts in that array 7 elements
# containing:
# - the handle of the window to which the message is addressed
# - the message identifier
# - the wParam argument
# - the lParam argument
# - the time when message occurs
# - the x coordinate at which message occurs
# - the y coordinate at which message occurs
#
BOOL
PeekMessage(handle, min=0, max=0, message=&PL_sv_undef)
HWND handle
UINT min
UINT max
SV* message
PREINIT:
MSG msg;
CODE:
ZeroMemory(&msg, sizeof(msg));
RETVAL = PeekMessage(&msg, handle, min, max, PM_NOREMOVE);
if(message != &PL_sv_undef) {
if(SvROK(message) && SvTYPE(SvRV(message)) == SVt_PVAV) {
av_clear((AV*) SvRV(message));
av_push((AV*) SvRV(message), newSViv(PTR2IV(msg.hwnd)));
av_push((AV*) SvRV(message), newSViv(msg.message));
av_push((AV*) SvRV(message), newSViv(msg.wParam));
av_push((AV*) SvRV(message), newSViv(msg.lParam));
av_push((AV*) SvRV(message), newSViv(msg.time));
av_push((AV*) SvRV(message), newSViv(msg.pt.x));
av_push((AV*) SvRV(message), newSViv(msg.pt.y));
} else {
W32G_WARN("Win32::GUI: fourth parameter to PeekMessage is not an array reference");
}
}
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Hook(MSG,CODEREF)
# Adds a new handler to the list of handlers for a particular window
# message / command / notification.
#
# Hook() can be used with the New Event Model and the Old Event Model. You
# can Hook() normal window messages, WM_COMMAND codes and WM_NOTIFY codes.
# You can add as many hooks for one message as you like. To remove hooks
# see UnHook().
#
# Here's an example Perl handler routine:
#
# sub click_handler {
# ($object, $wParam, $lParam, $type, $msgcode) = @_;
# print "Click handler called!\n";
# }
#
# Here, $object is the Perl object for the widget, $wParam and $lParam are
# the parameters received with the message, $type is the type of message
# (0, WM_NOTIFY or WM_COMMAND, see below), and $msgcode is the original
# numeric code for the message.
#
# If you call Hook() on a child widget, such as a button, the Hook will be
# called if the parent window receives WM_COMMAND and the code given with
# WM_COMMAND matches the MSG argument you passed to Hook(). Put simply,
# what this means is that things like
#
# $button->Hook(BN_CLICKED, \&button_clicked);
#
# will work. When your handler is called it will be passed a $type argument
# of WM_COMMAND (numeric 273).
#
# The same is true for WM_NOTIFY messages, although handlers defined for
# those are passed a $type argument of WM_NOTIFY (numeric 78).
#
# Any message that was not WM_NOTIFY or WM_COMMAND gets passed a $type of 0.
# It is important to check your $type argument. Certain codes for WM_COMMAND
# messages may conflict with codes for WM_NOTIFY messages or regular window
# messages, meaning the handler you defined for a particular WM_NOTIFY code
# may get triggered by a WM_COMMAND code. The $type argument is there to
# allow you to check this. The rule is to just return immediately if $type
# is not what you were expecting.
#
# If Hook() successfully added a hook for the event, it returns true. If
# the hook already exists (the coderef you gave is already in the list of
# hooks for the specified event), or if there was an error in creating the
# new hook, it returns false.
#
void
Hook(handle,msg,coderef)
HWND handle
I32 msg
SV* coderef
PREINIT:
LPPERLWIN32GUI_USERDATA perlud;
SV** arrayref;
AV* newarray;
int i;
SV** value;
PPCODE:
if(msg < 0) { msg = 0 - msg; }; // Looks wrong but if hooks are used correctly this should be OK.
if(SvOK(coderef) && SvROK(coderef) && SvTYPE(SvRV(coderef)) == SVt_PVCV) {
// We have a code reference.
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(handle, GWLP_USERDATA);
if(perlud->avHooks == NULL) {
perlud->avHooks = newAV();
}
// Check if array value for this message exists already:
arrayref = av_fetch(perlud->avHooks, msg, 0);
if(arrayref == NULL) {
// No array reference for this msg yet, so make one and insert our
// handler ref:
newarray = newAV();
av_push(newarray, coderef);
SvREFCNT_inc(coderef);
if(av_store(perlud->avHooks, msg, newRV_noinc((SV*) newarray)) == NULL) {
SvREFCNT_dec((SV*) newarray);
CROAK("AddHook failed to store new array reference.\n");
XSRETURN_NO;
}
}
else {
// There IS an array reference already, so add the handler.
// First, check the handler isn't already there:
for(i = 0; i <= (int) av_len((AV*) SvRV(*arrayref)); i++) {
value = av_fetch((AV*) SvRV(*arrayref), i,0);
if(sv_eq(*value,coderef)) {
XSRETURN_NO;
}
}
// Add the coderef:
av_push((AV*) SvRV(*arrayref), coderef);
SvREFCNT_inc(coderef);
}
XSRETURN_YES;
}
else {
CROAK("Usage: Hook(message, coderef)\n");
XSRETURN_NO;
}
###########################################################################
# (@)METHOD:UnHook(MSG,[CODEREF])
# Removes a specific code reference from the hooks listing for the given
# message, or removes all code references for the given message if no
# coderef is specified.
#
# Returns true on success, and false on failure (no such hook).
#
# See Hook() documentation for more information on hooks and their
# usage.
#
void
UnHook(handle,msg,coderef = NULL)
HWND handle
I32 msg
SV* coderef
PREINIT:
LPPERLWIN32GUI_USERDATA perlud;
SV** arrayref;
SV** removedvalue;
int i;
int count = 0;
PPCODE:
if(msg < 0) { msg = 0 - msg; };
if(coderef != NULL && !(SvOK(coderef) && SvROK(coderef) && SvTYPE(SvRV(coderef)) == SVt_PVCV)) {
CROAK("Usage: UnHook(message,[coderef]). What you gave as a coderef was not a code reference\n");
XSRETURN_NO;
}
else {
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(handle, GWLP_USERDATA);
if(perlud->avHooks == NULL) {
XSRETURN_NO;
}
else {
arrayref = av_fetch(perlud->avHooks, msg, 0);
if(arrayref == NULL) {
XSRETURN_NO;
}
else {
for(i = 0; i <= (int) av_len((AV*) SvRV(*arrayref)); i++) {
removedvalue = av_fetch((AV*) SvRV(*arrayref), i,0);
if(removedvalue != NULL && (coderef == NULL || sv_eq(*removedvalue,coderef)) ) {
/* SvREFCNT_dec(*removedvalue);
av_delete((AV*) SvRV(*arrayref), i, 0); */
av_delete((AV*) SvRV(*arrayref), i, G_DISCARD);
count++;
}
}
if(coderef == NULL || av_len((AV*) SvRV(*arrayref)) == -1) {
removedvalue = av_fetch(perlud->avHooks, msg, 0);
/* SvREFCNT_dec(*removedvalue);
av_delete(perlud->avHooks, msg, 0); */
av_delete(perlud->avHooks, msg, G_DISCARD);
}
XSRETURN_IV(count);
}
}
}
###########################################################################
# (@)METHOD:Result(HANDLE, RESULT)
# Explicitly set the result to be returned from a handler. For safety and
# backwards compatibility, results returned from Win32::GUI handlers are
# discarded. You can use this method (with GREAT CARE) to explicitly force
# a return value for your handler. Consult the API documentation for valid
# return values as they vary from message to message.
void
Result(handle, result)
HWND handle
int result
PREINIT:
LPPERLWIN32GUI_USERDATA perlud;
CODE:
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(handle, GWLP_USERDATA);
if(ValidUserData(perlud)) {
perlud->forceResult = (LRESULT) result;
XSRETURN_YES;
}
else
XSRETURN_NO;
###########################################################################
# (@)METHOD:SetFont(FONT)
# Sets the font of the window (FONT is a Win32::GUI::Font object).
LRESULT
SetFont(handle, font)
HWND handle
HFONT font
CODE:
RETVAL = SendMessage(handle, WM_SETFONT, (WPARAM) font, 0);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetFont(FONT)
# Gets the font of the window (returns an handle; use to get font details).
#
# $Font = $W->GetFont();
# %details = Win32::GUI::Font::Info( $Font );
LRESULT
GetFont(handle)
HWND handle
CODE:
RETVAL = SendMessage(handle, WM_GETFONT, 0, 0);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:SetRedraw(FLAG)
# Determines if a window is automatically redrawn when its content changes.
#
# B<FLAG> can be a true value to allow redraw, false to prevent it.
LRESULT
SetRedraw(handle, value)
HWND handle
WPARAM value
CODE:
RETVAL = SendMessage(handle, WM_SETREDRAW, value, 0);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:SetIcon(ICON, [TYPE])
# Sets the icon of the window; B<TYPE> can be 0 for the small icon, 1 for
# the big icon. Default is the same icon for small and big.
LRESULT
SetIcon(handle, icon, type=ICON_SMALL)
HWND handle
HICON icon
WPARAM type
CODE:
if (items > 2)
RETVAL = SendMessage(handle, WM_SETICON, type, (LPARAM) icon);
else {
SendMessage(handle, WM_SETICON, ICON_SMALL, (LPARAM) icon);
RETVAL = SendMessage(handle, WM_SETICON, ICON_BIG, (LPARAM) icon);
}
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Text([TEXT])
# (@)METHOD:Caption([TEXT])
# Sets or gets the text associated with a window or control. For example,
# for windows, this is the text in the titlebar of the window. For button
# controls, it's the text on the button, and so on. Text() and Caption()
# are synonymous with oneanother.
void
Text(handle,...)
HWND handle
ALIAS:
Win32::GUI::Caption = 1
PREINIT:
char *myBuffer;
int myLength;
PPCODE:
if(items > 2) {
CROAK("Usage: Text(handle, [value]);\n");
}
if(items == 1) {
myLength = GetWindowTextLength(handle)+1;
if(myLength) {
myBuffer = (char *) safemalloc(myLength);
if(GetWindowText(handle, myBuffer, myLength)) {
EXTEND(SP, 1);
XST_mPV(0, myBuffer);
safefree(myBuffer);
XSRETURN(1);
}
safefree(myBuffer);
}
XSRETURN_NO;
} else {
XSRETURN_IV((IV) SetWindowText(handle, (LPCTSTR) SvPV_nolen(ST(1))));
}
###########################################################################
# (@)METHOD:Move(X, Y)
# Moves a window to the given B<X> and B<Y> co-ordinates.
BOOL
Move(handle,x,y)
HWND handle
int x
int y
CODE:
RETVAL = SetWindowPos(handle, (HWND) NULL, x, y, 0, 0,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSIZE);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Resize(WIDTH, HEIGHT)
# Resizes a window to the given B<WIDTH> and B<HEIGHT>.
BOOL
Resize(handle,x,y)
HWND handle
int x
int y
CODE:
RETVAL = SetWindowPos(handle, (HWND) NULL, 0, 0, x, y,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetClientRect()
# Gets the client area rectangle and returns an array of left, top, right,
# and bottom co-ordinates if successful. Left and top will always be 0,
# right and bottom are equivalent to the width and height of the client
# area.
void
GetClientRect(handle)
HWND handle
PREINIT:
RECT myRect;
PPCODE:
if(GetClientRect(handle, &myRect)) {
EXTEND(SP, 4);
XST_mIV(0, myRect.left);
XST_mIV(1, myRect.top);
XST_mIV(2, myRect.right);
XST_mIV(3, myRect.bottom);
XSRETURN(4);
} else {
XSRETURN_UNDEF;
}
###########################################################################
# (@)METHOD:GetAbsClientRect()
# Gets the absolute screen co-ordinates of the client rectangle and returns
# an array of left, top, right, and bottom co-ordinates.
void
GetAbsClientRect(handle)
HWND handle
PREINIT:
WINDOWINFO pwi;
PPCODE:
pwi.cbSize = sizeof(WINDOWINFO);
if(GetWindowInfo(handle, &pwi)) {
EXTEND(SP, 4);
XST_mIV(0, pwi.rcClient.left);
XST_mIV(1, pwi.rcClient.top);
XST_mIV(2, pwi.rcClient.right);
XST_mIV(3, pwi.rcClient.bottom);
XSRETURN(4);
}
else {
XSRETURN_UNDEF;
}
###########################################################################
# (@)METHOD:GetWindowRect()
# Returns a four elements array defining the windows rectangle (left, top,
# right, bottom) in screen co-ordinates or undef on errors.
void
GetWindowRect(handle)
HWND handle
PREINIT:
RECT myRect;
PPCODE:
if(GetWindowRect(handle, &myRect)) {
EXTEND(SP, 4);
XST_mIV(0, myRect.left);
XST_mIV(1, myRect.top);
XST_mIV(2, myRect.right);
XST_mIV(3, myRect.bottom);
XSRETURN(4);
} else {
XSRETURN_UNDEF;
}
###########################################################################
# (@)METHOD:Width([WIDTH])
# Sets or retrieves the width of a window.
#
# See also Resize()
void
Width(handle,...)
HWND handle
PREINIT:
RECT myRect;
PPCODE:
if(items > 2) {
croak("Usage: Width(handle, [value]);\n");
}
if(!GetWindowRect(handle, &myRect)) XSRETURN_NO;
if(items == 1) {
EXTEND(SP, 1);
XST_mIV(0, (myRect.right-myRect.left));
XSRETURN(1);
} else {
if(SetWindowPos(handle, (HWND) NULL, 0, 0,
(int) SvIV(ST(1)),
(int) (myRect.bottom-myRect.top),
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_DEFERERASE)) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
###########################################################################
# (@)METHOD:Height([HEIGHT])
# Sets or retrieves the height of a window.
#
# See also Resize()
void
Height(handle,...)
HWND handle
PREINIT:
RECT myRect;
PPCODE:
if(items > 2) {
croak("Usage: Height(handle, [value]);\n");
}
if(!GetWindowRect(handle, &myRect)) XSRETURN_NO;
if(items == 1) {
EXTEND(SP, 1);
XST_mIV(0, (myRect.bottom-myRect.top));
XSRETURN(1);
} else {
if(SetWindowPos(handle, (HWND) NULL, 0, 0,
(int) (myRect.right-myRect.left),
(int) SvIV(ST(1)),
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_DEFERERASE)) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
###########################################################################
# (@)METHOD:Left([LEFT])
# Gets or sets the left co-ordinate of an object, relative to the object's
# parent if it has one, or absolute screen co-ordinate if it doesn't.
#
# See also AbsLeft()
# See also Move()
void
Left(handle,...)
HWND handle
PREINIT:
RECT myRect;
HWND parent;
POINT myPt;
PPCODE:
if(items > 2) {
croak("Usage: Left(handle, [value]);\n");
}
if(!GetWindowRect(handle, &myRect)) XSRETURN_NO;
myPt.x = myRect.left;
myPt.y = myRect.top;
parent = GetParent(handle);
if (parent && IsChild(parent, handle)) ScreenToClient(parent, &myPt);
if(items == 1) {
EXTEND(SP, 1);
XST_mIV(0, myPt.x);
XSRETURN(1);
} else {
if(SetWindowPos(
handle, (HWND) NULL,
(int) SvIV(ST(1)), (int) myPt.y,
0, 0,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_DEFERERASE
)) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
###########################################################################
# (@)METHOD:Top([TOP])
# Gets or sets the top co-ordinate of an object, relative to the object's
# parent if it has one, or absolute screen co-ordinate if it doesn't.
#
# See also AbsTop()
# See also Move()
void
Top(handle,...)
HWND handle
PREINIT:
RECT myRect;
HWND parent;
POINT myPt;
PPCODE:
if(items > 2) {
croak("Usage: Top(handle, [value]);\n");
}
if(!GetWindowRect(handle, &myRect)) XSRETURN_NO;
myPt.x = myRect.left;
myPt.y = myRect.top;
parent = GetParent(handle);
if (parent && IsChild(parent, handle)) ScreenToClient(parent, &myPt);
if(items == 1) {
EXTEND(SP, 1);
XST_mIV(0, myPt.y);
XSRETURN(1);
} else {
if(SetWindowPos(
handle, (HWND) NULL,
(int) myPt.x, (int) SvIV(ST(1)),
0, 0,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_DEFERERASE
)) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
###########################################################################
# (@)METHOD:AbsLeft([LEFT])
# Gets or sets the absolute left (screen) co-ordinate of a window.
#
# See also Left()
# See also Move()
void
AbsLeft(handle,...)
HWND handle
PREINIT:
RECT myRect;
HWND parent;
PPCODE:
if(!GetWindowRect(handle, &myRect)) {
XSRETURN_UNDEF;
}
/* Set */
if(items > 1) {
myRect.left = (LONG)SvIV(ST(1));
/* If we're a child window convert to parent's client co-ordinates */
if(parent = GetAncestor(handle, GA_PARENT)) {
ScreenToClient(parent, (LPPOINT)&myRect);
}
if(SetWindowPos(handle, NULL, (int)myRect.left, (int)myRect.top,
0, 0, SWP_NOZORDER | SWP_NOSIZE)) {
XSRETURN_YES;
}
else {
XSRETURN_NO;
}
}
/* Get */
EXTEND(SP, 1);
XST_mIV(0, myRect.left);
XSRETURN(1);
###########################################################################
# (@)METHOD:AbsTop([TOP])
# Gets or sets the absolute top (screen) co-ordinate of a window.
#
# See also Top()
# See also Move()
void
AbsTop(handle,...)
HWND handle
PREINIT:
RECT myRect;
HWND parent;
PPCODE:
if(!GetWindowRect(handle, &myRect)) {
XSRETURN_UNDEF;
}
/* Set */
if(items > 1) {
myRect.top = (LONG)SvIV(ST(1));
/* If we're a child window convert to parent's client co-ordinates */
if(parent = GetAncestor(handle, GA_PARENT)) {
ScreenToClient(parent, (LPPOINT)&myRect);
}
if(SetWindowPos(handle, NULL, (int)myRect.left, (int)myRect.top,
0, 0, SWP_NOZORDER | SWP_NOSIZE)) {
XSRETURN_YES;
}
else {
XSRETURN_NO;
}
}
/* Get */
EXTEND(SP, 1);
XST_mIV(0, myRect.top);
XSRETURN(1);
###########################################################################
# (@)METHOD:ScreenToClient(X, Y)
# Converts screen co-ordinates to client-area co-ordinates.
void
ScreenToClient(handle,x,y)
HWND handle
int x
int y
PREINIT:
POINT myPt;
PPCODE:
myPt.x = x;
myPt.y = y;
ScreenToClient(handle, &myPt);
EXTEND(SP, 2);
XST_mIV(0, myPt.x);
XST_mIV(1, myPt.y);
XSRETURN(2);
###########################################################################
# (@)METHOD:ClientToScreen(X, Y)
# Converts client-area co-ordinates to screen co-ordinates.
void
ClientToScreen(handle,x,y)
HWND handle
int x
int y
PREINIT:
POINT myPt;
PPCODE:
myPt.x = x;
myPt.y = y;
ClientToScreen(handle, &myPt);
EXTEND(SP, 2);
XST_mIV(0, myPt.x);
XST_mIV(1, myPt.y);
XSRETURN(2);
###########################################################################
# (@)METHOD:ScaleWidth()
# Returns the windows client area width.
DWORD
ScaleWidth(handle)
HWND handle
PREINIT:
RECT myRect;
CODE:
if(GetClientRect(handle, &myRect)) {
RETVAL = myRect.right;
} else {
RETVAL = 0;
}
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ScaleHeight()
# Returns the windows client area height.
DWORD
ScaleHeight(handle)
HWND handle
PREINIT:
RECT myRect;
CODE:
if(GetClientRect(handle, &myRect)) {
RETVAL = myRect.bottom;
} else {
RETVAL = 0;
}
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:BringWindowToTop()
# Brings a window to the foreground (on top of other windows). This does
# not make the window "always on top". If the window is already on top,
# it is activated. If the window is a child window, the top-level
# parent window associated with the child window is activated.
BOOL
BringWindowToTop(handle)
HWND handle
CODE:
RETVAL = BringWindowToTop(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ArrangeIconicWindows()
# Arranges all the minimized child windows of the specified parent window.
UINT
ArrangeIconicWindows(handle)
HWND handle
CODE:
RETVAL = ArrangeIconicWindows(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetDesktopWindow()
# Returns the handle of the desktop window.
HWND
GetDesktopWindow(...)
CODE:
RETVAL = GetDesktopWindow();
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetForegroundWindow()
# Returns the handle of the foreground window.
HWND
GetForegroundWindow(...)
CODE:
RETVAL = GetForegroundWindow();
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:SetForegroundWindow()
# Brings the window to the foreground.
BOOL
SetForegroundWindow(handle)
HWND handle
CODE:
RETVAL = SetForegroundWindow(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:IsZoomed()
# Returns TRUE if the window is maximized, FALSE otherwise.
BOOL
IsZoomed(handle)
HWND handle
CODE:
RETVAL = IsZoomed(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:IsIconic()
# Returns TRUE if the window is minimized, FALSE otherwise.
BOOL
IsIconic(handle)
HWND handle
CODE:
RETVAL = IsIconic(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:IsWindow()
# Returns TRUE if the window is a window, FALSE otherwise.
BOOL
IsWindow(handle)
HWND handle
CODE:
RETVAL = IsWindow(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:IsVisible()
# Returns TRUE if the window is visible, FALSE otherwise.
BOOL
IsVisible(handle)
HWND handle
CODE:
RETVAL = IsWindowVisible(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:IsEnabled()
# Returns TRUE if the window is enabled, FALSE otherwise.
BOOL
IsEnabled(handle)
HWND handle
CODE:
RETVAL = IsWindowEnabled(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Enable([FLAG])
# Enables (or disables) a window or control. Controls do not accept input
# when they are disabled.
#
# B<FLAG> should be 0 to disable the control (the same as calling Disable() on
# a control), or 1 to enable it.
#
# See also Disable()
BOOL
Enable(handle,flag=TRUE)
HWND handle
BOOL flag
CODE:
RETVAL = EnableWindow(handle, flag);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:Disable()
# Disables a window or control. Disabled widgets cannot be interacted with,
# and often change appearance to indicate that they are disabled. This is
# the same as Enable(0).
#
# See also Enable()
BOOL
Disable(handle)
HWND handle
CODE:
RETVAL = EnableWindow(handle, FALSE);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:OpenIcon()
# (@)METHOD:Restore()
# Restores a minimized window.
BOOL
OpenIcon(handle)
HWND handle
ALIAS:
Win32::GUI::Restore = 1
CODE:
RETVAL = OpenIcon(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:CloseWindow()
# (@)METHOD:Minimize()
# Minimizes a window.
BOOL
CloseWindow(handle)
HWND handle
ALIAS:
Win32::GUI::Minimize = 1
CODE:
RETVAL = CloseWindow(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:WindowFromPoint(X, Y)
# Returns the handle of the window at the specified screen position.
HWND
WindowFromPoint(x,y)
LONG x
LONG y
PREINIT:
POINT myPoint;
CODE:
myPoint.x = x;
myPoint.y = y;
RETVAL = WindowFromPoint(myPoint);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetTopWindow()
# Returns the handle of the foreground window.
HWND
GetTopWindow(handle)
HWND handle
CODE:
RETVAL = GetTopWindow(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetActiveWindow()
# Returns the handle of the active window.
HWND
GetActiveWindow(...)
CODE:
RETVAL = GetActiveWindow();
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:SetActiveWindow()
# Activates a window.
# Returns the handle of the previously active window or 0.
HWND
SetActiveWindow(handle)
HWND handle
CODE:
RETVAL = SetActiveWindow(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetDlgItem(ID)
# Returns the handle of a control in the dialog box given its B<ID>.
HWND
GetDlgItem(handle,identifier)
HWND handle
int identifier
CODE:
RETVAL = GetDlgItem(handle, identifier);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetFocus()
# Returns the handle of the window that has the keyboard focus.
HWND
GetFocus(...)
CODE:
RETVAL = GetFocus();
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:SetFocus()
# Set focus to a window.
HWND
SetFocus(handle)
HWND handle
CODE:
RETVAL = SetFocus(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:SetCapture()
# Assigns the mouse capture to a window.
HWND
SetCapture(handle)
HWND handle
CODE:
RETVAL = SetCapture(handle);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetCapture()
# Returns the handle of the window that has the captured the mouse.
# If no window has captured the mouse zero is returned.
HWND
GetCapture()
CODE:
RETVAL = GetCapture();
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ReleaseCapture()
# Releases the mouse capture.
BOOL
ReleaseCapture(...)
CODE:
RETVAL = ReleaseCapture();
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:ShellExecute(window,operation,file,parameters,directory,showcmd)
#
# Performs an operation on a file.
#
# B<Operation>. A string that specifies the action to be performed. The set of available action verbs depends
# on the particular file or folder. Generally, the actions available from an object's shortcut menu are
# available verbs.
# edit - Launches an editor and opens the document for editing. If File is not a document file,
# the function will fail.
# explore - Explores the folder specified by File.
# find - Initiates a search starting from the specified directory.
# open - Opens the file specified by the File parameter. The file can be an executable file,
# a document file, or a folder.
# print - Prints the document file specified by lpFile. If lpFile is not a document file,
# the function will fail.
# ""(NULL) - For systems prior to Microsoft Windows 2000, the default verb is used if it is valid
# and available in the registry. If not, the "open" verb is used. For Windows 2000 and
# later systems, the default verb is used if available. If not, the "open" verb is used.
# If neither verb is available, the system uses the first verb listed in the registry.
#
# B<File>. A string that specifies the file or object on which to execute the specified verb. To specify
# a Shell namespace object, pass the fully qualified parse name. Note that not all verbs are supported on
# all objects. For example, not all document types support the "print" verb.
#
# B<Parameters>. If the File parameter specifies an executable file, Parameters is a string that specifies
# the parameters to be passed to the application. The format of this string is determined by the verb that
# is to be invoked. If File specifies a document file, Parameters should be NULL.
#
# B<Directory>. A string that specifies the default directory.
#
# B<ShowCmd>. Flags that speciow an application is to be displayed when it is opened. If File specifies a
# document file, the flag is simply passed to the associated application. It is up to the application to
# decide how to handle it.
#
# 0 SW_HIDE Hides the window and activates another window.
# 3 SW_MAXIMIZE Maximizes the specified window.
# 6 SW_MINIMIZE Minimizes the specified window and activates the next top-level window in the z-order.
# 9 SW_RESTORE Activates and displays the window. If the window is minimized or maximized,
# Windows restores it to its original size and position. An application should specify
# this flag when restoring a minimized window.
# 5 SW_SHOW Activates the window and displays it in its current size and position.
# 10 SW_SHOWDEFAULT Sets the show state based on the SW_ flag specified in the STARTUPINFO structure
# passed to the CreateProcess function by the program that started the application.
# An application should call ShowWindow with this flag to set the initial show state of
# its main window.
# 2 SW_SHOWMINIMIZED Activates the window and displays it as a minimized window.
# 7 SW_SHOWMINNOACTIVE Displays the window as a minimized window. The active window remains active.
# 8 SW_SHOWNA Displays the window in its current state. The active window remains active.
# 4 SW_SHOWNOACTIVATE Displays a window in its most recent size and position. The active window remains active.
# 1 SW_SHOWNORMAL Activates and displays a window. If the window is minimized or maximized, Windows
# restores it to its original size and position. An application should specify this flag
# when displaying the window for the first time.
#
# Returns a value greater than 32 if successful, or an error value that is less than or equal to 32 otherwise.
# The following table lists the error values.
#
# 0 The operating system is out of memory or resources.
# 3 ERROR_PATH_NOT_FOUND The specified path was not found.
# 11 ERROR_BAD_FORMAT The .exe file is invalid (non-Microsoft Win32 .exe or error in .exe image).
# 5 SE_ERR_ACCESSDENIED The operating system denied access to the specified file.
# 27 SE_ERR_ASSOCINCOMPLETE The file name association is incomplete or invalid.
# 30 SE_ERR_DDEBUSY The Dynamic Data Exchange (DDE) transaction could not be completed because
# other DDE transactions were being processed.
# 29 SE_ERR_DDEFAIL The DDE transaction failed.
# 28 SE_ERR_DDETIMEOUT The DDE transaction could not be completed because the request timed out.
# 32 SE_ERR_DLLNOTFOUND The specified dynamic-link library (DLL) was not found.
# 2 SE_ERR_FNF The specified file was not found.
# 31 SE_ERR_NOASSOC There is no application associated with the given file name extension. This
# error will also be returned if you attempt to print a file that is not printable.
# 8 SE_ERR_OOM There was not enough memory to complete the operation.
# 3 SE_ERR_PNF The specified path was not found.
# 26 SE_ERR_SHARE A sharing violation occurred.
#
# Examples:
#
# Open a web page in the default browser
# my $exitval = $win->ShellExecute('open','http://www.perl.org','','',1);
#
# Open a text file in nodepad
# my $exitval = $win->ShellExecute('open','notepad.exe','readme.txt','',1) ;
IV
ShellExecute(window,operation,file,parameters,directory,showcmd)
HWND window
LPCTSTR operation
LPCTSTR file
LPCTSTR parameters
LPCTSTR directory
INT showcmd
CODE:
RETVAL = (IV) ShellExecute(window,operation,file,parameters,directory,showcmd);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetWindowThreadProcessId()
# Returns a two elements array containing the thread and the process
# identifier for the specified window.
void
GetWindowThreadProcessId(handle)
HWND handle
PREINIT:
DWORD tid;
DWORD pid;
PPCODE:
tid = GetWindowThreadProcessId(handle, &pid);
EXTEND(SP, 2);
XST_mIV(0, tid);
XST_mIV(1, pid);
XSRETURN(2);
###########################################################################
# (@)METHOD:AttachThreadInput(FROM, TO, [FLAG])
# If you have multiple windows running in different threads, this function
# allows you to attach one thread's input processor to a different thread.
#
# For example, you can redirect thread A's input to thread B, and then
# call SetFocus on an object running in thread B to set the keyboard focus
# to that object. You would not normally be able to do this.
#
# B<FROM> and B<TO> should be thread IDs. B<FLAG> should be non-zero to attach the
# threads (the default operation if B<FLAG> is not specified), or zero to
# detach the threads.
#
# see also GetWindowThreadProcessId()
BOOL
AttachThreadInput(from,to,flag=TRUE)
DWORD from
DWORD to
BOOL flag
CODE:
RETVAL = AttachThreadInput(from, to, flag);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetTextExtentPoint32(STRING, [FONT])
# Returns a two elements array containing the x and y size of the
# specified B<STRING> in the window (eventually with the speficied B<FONT>), or
# undef on errors.
void
GetTextExtentPoint32(handle,string,font=NULL)
HWND handle
char * string
HFONT font
PREINIT:
STRLEN cbString;
char *szString;
HDC hdc;
SIZE mySize;
PPCODE:
szString = SvPV(ST(1), cbString);
hdc = GetDC(handle);
#ifdef PERLWIN32GUI_DEBUG
printf("XS(GetTextExtentPoint32).font=0x%x\n", font);
printf("XS(GetTextExtentPoint32).string='%s'\n", string);
#endif
if(font) SelectObject(hdc, (HGDIOBJ) font);
if(GetTextExtentPoint32(hdc, szString, (int)cbString, &mySize)) {
EXTEND(SP, 2);
XST_mIV(0, mySize.cx);
XST_mIV(1, mySize.cy);
ReleaseDC(handle, hdc);
XSRETURN(2);
} else {
ReleaseDC(handle, hdc);
XSRETURN_UNDEF;
}
###########################################################################
# (@)METHOD:TrackPopupMenu(MENU [, X, Y [, LEFT, TOP, RIGHT, BOTTOM] [, FLAGS [, CODEREF]]])
# Displays the menu B<MENU> at the specified co-ordinates (X,Y) and tracks the
# selection of items on the menu. X and Y are absolute screen co-ordinates.
#
# If X and Y are not provided, uses the current cursor position.
#
# If LEFT, TOP, RIGHT and BOTTOM are provided they describe a rectangle in absolute screen
# co-ordinates over which the menu will not be drawn (the excluded rectangle).
#
# The following flags can be set (combine flags with bitwise OR (|) )
# 0x0000 TPM_LEFTBUTTON Menu items can only be selected with left mouse button
# 0x0002 TPM_RIGHTBUTTON Menu items can be selected with either left or right mouse button
# 0x0000 TPM_LEFTALIGN Menu is aligned to the left of the given X co-ordinate
# 0x0004 TPM_CENTERALIGN Menu is centered on the given X co-ordinate
# 0x0008 TPM_RIGHTALIGN Menu is aligned to the right of the given X co-ordinate
# 0x0000 TPM_TOPALIGN Menu is aligned above the given Y co-ordinate
# 0x0010 TPM_VCENTERALIGN Menu is centered on the given Y co-ordinate
# 0x0020 TPM_BOTTOMALIGN Menu is aligned below the given Y co-ordinate
# 0x0100 TPM_RETURNCMD TrackPopupMenu returns the selected menu item identifier in the return value
# 0x0400 TPM_HORPOSANIMATION Menu will be animated from left to right (ignored if menu fading is on)
# 0x0800 TPM_HORNEGANIMATION Menu will be animated from right to left (ignored if menu fading is on)
# 0x1000 TPM_VERPOSANIMATION Menu will be animated from top to bottom (ignored if menu fading is on)
# 0x2000 TPM_VERNEGANIMATION Menu will be animated from bottom to top (ignored if menu fading is on)
# 0x4000 TPM_NOANIMATION Menu will not be animated and will not "fade" in and out even if menu
# fading is enabled
# 0x0001 TPM_RECURSE Allows you to display a menu when another menu is already displayed.
# This is intended to support context menus within a menu. (Windows 2000/XP only)
#
# The default flags are C<TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON>
#
# If an excluded rectangle is spefified then the following flags may also be used, and TPM_VERTICAL is added to
# the default flags:
# 0x0000 TPM_HORIZONTAL If the menu cannot be shown at the specified location without overlapping
# the excluded rectangle, the system tries to accommodate the requested
# horizontal alignment before the requested vertical alignment.
# 0x0040 TPM_VERTICAL If the menu cannot be shown at the specified location without overlapping
# the excluded rectangle, the system tries to accommodate the requested
# vertical alignment before the requested horizontal alignment.
#
# If you specify C<TPM_RETURNCMD>, then the menu item ID of the selected item is returned. If an error
# occurs or the user does not select an item, zero is returned.
# If you do not specify C<TPM_RETURNCMD>, the return value will be nonzero on success or zero on failure.
#
# If B<CODEREF> is provided, then it is a code reference to a callback procedure that will be called for windows
# events that occur while the menu is displayed (normally such events are not available, as TrackPopupMenu has
# its own internal event loop). The callback will recieve a reference to the Win32::GUI object used to call
# TrackPopupMenu on, and the message code, wParam and lParam of the event that occured. The callback should
# return nothing or 1 to allow the event to be processed normally, or 0 to prevent the event being passed to the
# default event handler. See MSDN documentation for SetWindowsHookEx with idHook set to WH_MSGFILTER for
# the full gore.
#
# The callback prototype is:
#
# sub callback {
# my ($self, $message, $wParam, $lParam) = @_;
#
# # Process messages you are interested in
#
# return;
# }
#
BOOL
TrackPopupMenu(handle,hmenu, ... )
HWND handle
HMENU hmenu
PREINIT:
int x = 0;
int y = 0;
UINT flags = TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON;
LPTPMPARAMS lptpm = (LPTPMPARAMS) NULL;
TPMPARAMS tpm;
SV* coderef = (SV*) NULL;
HHOOK hhook = NULL;
LPPERLWIN32GUI_USERDATA perlud;
AV* newarray;
POINT pt;
CODE:
switch (items) {
case 10: coderef = ST(9);
case 9: flags = (UINT)SvIV(ST(8));
case 8: tpm.rcExclude.bottom = (LONG)SvIV(ST(7));
tpm.rcExclude.right = (LONG)SvIV(ST(6));
tpm.rcExclude.top = (LONG)SvIV(ST(5));
tpm.rcExclude.left = (LONG)SvIV(ST(4));
tpm.cbSize = sizeof(TPMPARAMS);
y = (int)SvIV(ST(3));
x = (int)SvIV(ST(2));
break;
case 6: coderef = ST(5);
case 5: flags = (UINT)SvIV(ST(4));
case 4: y = (int)SvIV(ST(3));
x = (int)SvIV(ST(2));
break;
case 2: if(GetCursorPos(&pt)) {
y = pt.y;
x = pt.x;
}
break;
default:
CROAK("Usage: TrackPopupMenu(handle, menu, [x, y, [left, top, right, bottom], [flag, [coderef]]])\n");
break;
}
// if given a coderef, check that it actually is one
if(coderef != NULL && !(SvOK(coderef) && SvROK(coderef) && SvTYPE(SvRV(coderef)) == SVt_PVCV)) {
W32G_WARN("TrackPopupMenu argument 'coderef' must be a code reference - callback not applied");
coderef = NULL; // don't set up the hook
}
// if we have a coderef, then store it temporarily in the hooks array so that we can access
// it in the callback, and if successful, register the callback hook handler
if(coderef != NULL) {
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(handle, GWLP_USERDATA);
if(ValidUserData(perlud)) {
if(perlud->avHooks == NULL) {
perlud->avHooks = newAV();
}
// Check if there is already a handler for this message (there shouldn't be)
if(av_fetch(perlud->avHooks, WM_TRACKPOPUP_MSGHOOK, 0) == NULL) {
// No array reference for this msg yet, so make one and insert our
// handler ref:
newarray = newAV();
av_push(newarray, coderef);
SvREFCNT_inc(coderef); // needed so that the ref count remains the same after we free
if(av_store(perlud->avHooks, WM_TRACKPOPUP_MSGHOOK, newRV_noinc((SV*) newarray)) == NULL) {
// Failed to store new array
SvREFCNT_dec((SV*) newarray);
W32G_WARN("TrackPopupMenu failed to store 'coderef' - callback not applied");
coderef = NULL; // don't set up the hook
}
}
else {
// there's an existing hook for the message value we've chosen to use.
// this means someone called hook() with the message code 0xBFFF !!
W32G_WARN("TrackPopupMenu found an existing 'coderef' - callback not applied");
coderef = NULL; // don't set up the hook
}
}
else {
coderef = NULL; // don't set up the hook
}
// only set up the hook if we installed the callback
if(coderef != NULL) {
hhook = SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)WindowsHookMsgProc, (HINSTANCE)NULL, GetWindowThreadProcessId(handle, (LPDWORD)NULL));
}
}
// Display the menu
SetForegroundWindow(handle);
RETVAL = TrackPopupMenuEx(hmenu, flags, x, y, handle, lptpm);
SetForegroundWindow(handle);
if(coderef != NULL) {
if(hhook != NULL) {
UnhookWindowsHookEx(hhook); // release the windows hook
}
// remove the temporary value stored in the hooks array
av_delete(perlud->avHooks, WM_TRACKPOPUP_MSGHOOK, G_DISCARD);
}
OUTPUT:
RETVAL
###########################################################################
# (@)INTERNAL:SetTimer(HANDLE, ID, ELAPSE)
UINT_PTR
SetTimer(handle,id,elapse)
HWND handle
UINT_PTR id
UINT elapse
CODE:
RETVAL = SetTimer(handle, id, elapse, NULL);
OUTPUT:
RETVAL
###########################################################################
# (@)INTERNAL:KillTimer(HANDLE, ID)
UINT
KillTimer(handle,id)
HWND handle
UINT_PTR id
CODE:
RETVAL = KillTimer(handle, id);
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:GetEffectiveClientRect(HANDLE, @CONTROLS)
# Returns the left, top, right and bottom co-ordinates of a rectangle that
# can accommodate all the controls specified. The elements of B<@CONTROLS>
# should be control identifiers.
void
GetEffectiveClientRect(handle,...)
HWND handle
PREINIT:
LPINT controls;
int i, c;
RECT r;
PPCODE:
c = 0;
controls = (LPINT) safemalloc(sizeof(INT)*items*2);
for(i=1;i<items;i++) {
controls[c++] = 1;
controls[c++] = (INT) SvIV(ST(i));
}
controls[c++] = 0;
controls[c++] = 0;
GetEffectiveClientRect(handle, &r, controls);
EXTEND(SP, 4);
XST_mIV(0, r.left);
XST_mIV(1, r.top);
XST_mIV(2, r.right);
XST_mIV(3, r.bottom);
XSRETURN(4);
###########################################################################
# (@)METHOD:DialogUI(HANDLE, [FLAG])
# Gets or sets whether a window accepts dialog-box style input (tab between
# fields, accelerator keys etc). B<FLAG> should be 1 to enable this functionality,
# or 0 to disable it.
#
# See also new Win32::GUI::DialogBox()
void
DialogUI(handle,...)
HWND handle
PREINIT:
LPPERLWIN32GUI_USERDATA perlud;
PPCODE:
if(items > 2) {
CROAK("Usage: DialogUI(handle, [value]);\n");
}
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(handle, GWLP_USERDATA);
if( ! ValidUserData(perlud) ) {
XSRETURN_UNDEF;
} else {
if(items == 1) {
XSRETURN_IV( (IV) perlud->dwPlStyle & PERLWIN32GUI_DIALOGUI );
} else {
SwitchBit(perlud->dwPlStyle, PERLWIN32GUI_DIALOGUI, SvIV(ST(1)));
XSRETURN_IV( (IV) perlud->dwPlStyle & PERLWIN32GUI_DIALOGUI );
}
}
###########################################################################
# (@)METHOD:TrackMouse([TIMEOUT=HOVER_DEFAULT, EVENTS=TME_HOVER|TME_LEAVE])
# Causes the window to receive messages when the mouse pointer leaves a
# window or hovers over a window for a specified amount of time (B<TIMEOUT>, in
# milliseconds).
#
# B<EVENTS> can be set to one or more of the following values (ORed together):
#
# 0x0001 TME_HOVER Makes the window receive WM_MOUSEHOVER messages when the mouse hovers over it.
# 0x0002 TME_LEAVE Makes the window receive a WM_MOUSELEAVE message when the mouse leaves it.
# 0x0010 TME_NONCLIENT Specifies that the non-client area should be included when tracking the mouse.
# The window will receive WM_NCMOUSEHOVER and WM_NCMOUSELEAVE messages depending
# on whether TME_HOVER and/or TME_LEAVE are set.
#
# See also UntrackMouse()
BOOL
TrackMouse(handle, timeout=HOVER_DEFAULT, events=TME_HOVER|TME_LEAVE)
HWND handle
DWORD timeout
DWORD events
PREINIT:
TRACKMOUSEEVENT tme;
CODE:
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.hwndTrack = handle;
tme.dwFlags = events;
tme.dwHoverTime = timeout;
RETVAL = _TrackMouseEvent( &tme );
OUTPUT:
RETVAL
###########################################################################
# (@)METHOD:UntrackMouse()
# Disables the tracking of mouse hover or leave events for a window.
#
# See also TrackMouse()
BOOL
UntrackMouse(handle)
HWND handle
PREINIT:
TRACKMOUSEEVENT tme;
CODE:
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.hwndTrack = handle;
tme.dwFlags = TME_QUERY;
tme.dwHoverTime = 0;
if(_TrackMouseEvent( &tme )) {
tme.dwFlags = tme.dwFlags | TME_CANCEL;
RETVAL = _TrackMouseEvent( &tme );
} else {
RETVAL = FALSE;
}
OUTPUT:
RETVAL
# TODO: GetIconInfo
###########################################################################
# DC-related functions (2D window graphic...)
###########################################################################
###########################################################################
# (@)METHOD:PlayEnhMetaFile(FILENAME)
# Displays the picture stored in the specified enhanced-format metafile.
# This function use current window device context (-DC).
int
PlayEnhMetaFile(handle,filename)
HWND handle
LPCTSTR filename
PREINIT:
HV* self;
HDC hdc;
SV** tmp;
HENHMETAFILE hmeta;
RECT rect;
CODE:
self = (HV*) SvRV(ST(0));
tmp = hv_fetch_mg(NOTXSCALL self, "-DC", 3, 0);
if(tmp == NULL) {
RETVAL = -1;
} else {
hdc = INT2PTR(HDC,SvIV(*tmp));
if(hmeta = GetEnhMetaFile(filename)) {
GetClientRect(handle, &rect);
RETVAL = PlayEnhMetaFile(hdc, hmeta, &rect);
DeleteEnhMetaFile(hmeta);
} else {
#ifdef PERLWIN32GUI_DEBUG
printf("XS(PlayEnhMetaFile): GetEnhMetaFile failed, error = %d\n", GetLastError());
#endif
RETVAL = 0;
}
}
OUTPUT:
RETVAL