#include "GUI.h"
#define CREATE_CONTROL_TABLE(n,T) \
T = { \
Window##n, \
DialogBox##n, \
Label##n, \
Button##n, \
Textfield##n, \
Listbox##n, \
Combobox##n, \
Checkbox##n, \
RadioButton##n, \
Groupbox##n, \
Toolbar##n, \
ProgressBar##n, \
StatusBar##n, \
TabStrip##n, \
RichEdit##n, \
ListView##n, \
TreeView##n, \
Trackbar##n, \
UpDown##n, \
Tooltip##n, \
Animation##n, \
Rebar##n, \
Header##n, \
ComboboxEx##n, \
DateTime##n, \
Graphic##n, \
Splitter##n, \
MDIFrame##n, \
MDIClient##n, \
MDIChild##n, \
MonthCal##n \
};
CREATE_CONTROL_TABLE(_onPreCreate,
void
(*OnPreCreate[])(NOTXSPROC LPPERLWIN32GUI_CREATESTRUCT));
CREATE_CONTROL_TABLE(_onParseOption,
BOOL
(*OnParseOption[])(NOTXSPROC
char
*, SV*,LPPERLWIN32GUI_CREATESTRUCT));
CREATE_CONTROL_TABLE(_onPostCreate,
void
(*OnPostCreate[])(NOTXSPROC
HWND
, LPPERLWIN32GUI_CREATESTRUCT));
CREATE_CONTROL_TABLE(_onParseEvent,
BOOL
(*OnParseEvent[])(NOTXSPROC
char
*,
int
*));
CREATE_CONTROL_TABLE(_onEvent,
int
(*OnEvent[])(NOTXSPROC LPPERLWIN32GUI_USERDATA,
UINT
,
WPARAM
,
LPARAM
));
void
Perlud_Free(NOTXSPROC LPPERLWIN32GUI_USERDATA perlud) {
if
(perlud != NULL) {
HWND
hwnd_self = SvOK(perlud->svSelf) ? handle_From(NOTXSCALL perlud->svSelf) : NULL;
if
(perlud->hvEvents != NULL) {
if
(SvREFCNT(perlud->hvEvents) != 1)
W32G_WARN(
"hvEvents ref count not 1 during destruction - please report this"
);
SvREFCNT_dec(perlud->hvEvents);
perlud->hvEvents = NULL;
}
if
(perlud->avHooks != NULL) {
if
(SvREFCNT(perlud->avHooks) != 1)
W32G_WARN(
"avHooks ref count not 1 during destruction - please report this"
);
SvREFCNT_dec(perlud->avHooks);
perlud->avHooks = NULL;
}
if
(perlud->svSelf != NULL && SvREFCNT(perlud->svSelf) > 0) {
if
(SvOK(perlud->svSelf)) {
HWND
parent = GetParent(hwnd_self);
if
(parent != NULL && *perlud->szWindowName !=
'\0'
) {
SV* SvParent = SV_SELF_FROM_WINDOW(parent);
if
(SvParent != NULL && SvROK(SvParent)) {
MAGIC* mg;
if
( (mg = mg_find(SvRV(SvParent), PERL_MAGIC_tied)) && SvROK(mg->mg_obj) ) {
hv_delete((HV*) SvRV(SvParent), perlud->szWindowName,
strlen
(perlud->szWindowName), G_DISCARD);
}
}
}
}
SvREFCNT_dec(perlud->svSelf);
perlud->svSelf = NULL;
}
if
(perlud->userData != NULL) {
if
(SvREFCNT(perlud->userData) != 1)
W32G_WARN(
"userData ref count not 1 during destruction - please report this"
);
SvREFCNT_dec(perlud->userData);
perlud->userData = NULL;
}
if
(perlud->bDeleteBackgroundBrush && perlud->hBackgroundBrush != NULL) {
DeleteObject((
HGDIOBJ
) perlud->hBackgroundBrush);
}
if
(hwnd_self && perlud->WndProc) {
SetWindowLongPtr(hwnd_self, GWLP_WNDPROC, (
LONG_PTR
)(perlud->WndProc));
}
safefree (perlud);
}
}
SV *
SV_SELF_FROM_WINDOW(
HWND
hwnd) {
LPPERLWIN32GUI_USERDATA perlud;
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if
( ValidUserData(perlud) ) {
return
perlud->svSelf;
}
else
{
return
NULL;
}
}
static
void
hv_magic_check (NOTXSPROC HV *hv,
bool
*needs_copy,
bool
*needs_store)
{
MAGIC *mg = SvMAGIC(hv);
*needs_copy = FALSE;
*needs_store = TRUE;
while
(mg) {
if
(isUPPER(mg->mg_type)) {
*needs_copy = TRUE;
switch
(mg->mg_type) {
case
'P'
:
case
'S'
:
*needs_store = FALSE;
}
}
#ifdef PERLWIN32GUI_STRONGDEBUG
printf
(
"!XS(hv_magic_check) magic='%c' needs_store='%d'\n"
, mg->mg_type, *needs_store);
#endif
mg = mg->mg_moremagic;
}
}
SV**
hv_fetch_mg(NOTXSPROC HV *hv,
char
*key, U32 klen, I32 lval) {
SV** tempsv;
tempsv = hv_fetch(hv, key, klen, lval);
if
(SvMAGICAL(hv)) mg_get(*tempsv);
return
tempsv;
}
SV**
hv_store_mg(NOTXSPROC HV *hv,
char
*key, U32 klen, SV* val, U32 hash) {
SV** tempsv;
tempsv = hv_store(hv, key, klen, val, hash);
if
(SvMAGICAL(hv)) mg_set(val);
return
tempsv;
}
HWND
handle_From(NOTXSPROC SV *pSv) {
HWND
hReturn = 0;
if
(NULL != pSv) {
if
( SvROK(pSv)) {
SV **pHv;
pHv = hv_fetch_mg(NOTXSCALL (HV*) SvRV(pSv),
"-handle"
, 7, 0);
if
(pHv != NULL) {
hReturn = INT2PTR(
HWND
,SvIV(*pHv));
}
}
else
{
hReturn = INT2PTR(
HWND
,SvIV(pSv));
}
}
return
(hReturn);
}
char
*classname_From(NOTXSPROC SV *pSv) {
char
*pszName = NULL;
if
(NULL != pSv) {
if
(SvROK(pSv)) {
SV **pHv;
pHv = hv_fetch_mg(NOTXSCALL (HV*) SvRV(pSv),
"-name"
, 5, 0);
if
(pHv != NULL) {
pszName = SvPV_nolen(*pHv);
}
}
else
{
pszName = SvPV_nolen(pSv);
}
}
return
(pszName);
}
WNDPROC GetDefClassProc (NOTXSPROC
const
char
*Name) {
HV* hash;
SV** wndproc;
hash = perl_get_hv(
"Win32::GUI::DefClassProc"
, FALSE);
wndproc = hv_fetch_mg(NOTXSCALL hash, (
char
*) Name,
strlen
(Name), FALSE);
if
(wndproc == NULL)
return
NULL;
return
INT2PTR(WNDPROC,SvIV(*wndproc));
}
BOOL
SetDefClassProc (NOTXSPROC
const
char
*Name, WNDPROC DefClassProc) {
HV* hash = perl_get_hv(
"Win32::GUI::DefClassProc"
, FALSE);
return
(hv_store_mg(NOTXSCALL hash, (
char
*) Name,
strlen
(Name), newSViv(PTR2IV(DefClassProc)), 0) != NULL);
}
COLORREF
SvCOLORREF(NOTXSPROC SV* c) {
SV** t;
int
r;
int
g;
int
b;
char
html_color[8];
char
html_color_component[3];
ZeroMemory(html_color, 8);
ZeroMemory(html_color_component, 3);
r = 0;
g = 0;
b = 0;
if
(SvROK(c) && SvTYPE(SvRV(c)) == SVt_PVAV) {
t = av_fetch((AV*)SvRV(c), 0, 0);
if
(t != NULL) {
r = SvIV(*t);
}
t = av_fetch((AV*)SvRV(c), 1, 0);
if
(t!= NULL) {
g = SvIV(*t);
}
t = av_fetch((AV*)SvRV(c), 2, 0);
if
(t != NULL) {
b = SvIV(*t);
}
return
RGB((
BYTE
) r, (
BYTE
) g, (
BYTE
) b);
}
else
{
if
(SvPOK(c)) {
strncpy
(html_color, SvPV_nolen(c), 7);
if
(
strncmp
(html_color,
"#"
, 1) == 0) {
strncpy
(html_color_component, html_color+1, 2);
*(html_color_component+2) = 0;
sscanf
(html_color_component,
"%x"
, &r);
strncpy
(html_color_component, html_color+3, 2);
*(html_color_component+2) = 0;
sscanf
(html_color_component,
"%x"
, &g);
strncpy
(html_color_component, html_color+5, 2);
*(html_color_component+2) = 0;
sscanf
(html_color_component,
"%x"
, &b);
return
RGB((
BYTE
) r, (
BYTE
) g, (
BYTE
) b);
}
else
{
return
(
COLORREF
) SvIV(c);
}
}
else
{
return
(
COLORREF
) SvIV(c);
}
}
}
HWND
CreateTooltip(
NOTXSPROC
HV* parent
) {
HWND
hTooltip;
HWND
hParent;
SV** t;
t = hv_fetch_mg(NOTXSCALL parent,
"-handle"
, 7, 0);
if
(t != NULL) {
hParent = INT2PTR(
HWND
,SvIV(*t));
}
else
{
return
NULL;
}
hTooltip = CreateWindowEx(
0, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hParent, NULL, NULL,
NULL
);
if
(hTooltip != NULL) {
SetWindowPos(
hTooltip, HWND_TOPMOST,0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
);
hv_store_mg(NOTXSCALL parent,
"-tooltip"
, 8, newSViv(PTR2IV(hTooltip)), 0);
}
return
hTooltip;
}
void
CalcControlSize(
NOTXSPROC
LPPERLWIN32GUI_CREATESTRUCT perlcs,
int
add_x,
int
add_y) {
SIZE mySize;
HDC
hdc;
SV** font;
HFONT
hfont, oldhfont;
if
(perlcs->cs.lpszName != NULL) {
if
(perlcs->cs.cx == 0 || perlcs->cs.cy == 0) {
hdc = GetDC(perlcs->cs.hwndParent);
if
(perlcs->hFont != NULL) {
hfont = perlcs->hFont;
}
else
{
hfont = (
HFONT
) GetStockObject(DEFAULT_GUI_FONT);
if
(perlcs->hvParent != NULL) {
font = hv_fetch_mg(NOTXSCALL perlcs->hvParent,
"-font"
, 5, FALSE);
if
(font != NULL && SvOK(*font)) {
hfont = (
HFONT
) handle_From(NOTXSCALL *font);
}
}
}
oldhfont = (
HFONT
)SelectObject(hdc, hfont);
if
(GetTextExtentPoint32(
hdc, perlcs->cs.lpszName,
strlen
(perlcs->cs.lpszName), &mySize
)) {
if
(perlcs->cs.cx == 0) perlcs->cs.cx = mySize.cx + add_x;
if
(perlcs->cs.cy == 0) perlcs->cs.cy = mySize.cy + add_y;
}
SelectObject(hdc, oldhfont);
ReleaseDC(perlcs->cs.hwndParent, hdc);
}
}
}
BOOL
GetObjectName(NOTXSPROC
HWND
hwnd,
char
*Name) {
LPPERLWIN32GUI_USERDATA perlud;
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if
( ValidUserData(perlud) ) {
if
(NULL != perlud->szWindowName) {
strcat
(Name, (
char
*) perlud->szWindowName);
return
TRUE;
}
else
{
return
FALSE;
}
}
else
{
return
FALSE;
}
}
BOOL
GetObjectNameAndClass(NOTXSPROC
HWND
hwnd,
char
*Name,
int
*obj_class) {
LPPERLWIN32GUI_USERDATA perlud;
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if
( ValidUserData(perlud) ) {
if
(NULL != perlud->szWindowName) {
strcat
(Name, (
char
*) perlud->szWindowName);
*obj_class = perlud->iClass;
return
TRUE;
}
else
{
return
FALSE;
}
}
else
{
return
FALSE;
}
}
SV* CreateObjectWithHandle(NOTXSPROC
char
* class_name,
HWND
handle) {
HV* hv = newHV();
hv_store(hv,
"-handle"
, 7, newSViv(PTR2IV(handle)), 0);
SV* cv = sv_2mortal(newRV((SV*)hv));
sv_bless(cv, gv_stashpv(class_name, 0));
SvREFCNT_dec(hv);
return
cv;
}
HMENU
GetMenuFromID(NOTXSPROC
int
nID) {
HV* hash;
SV** handle;
char
temp[80];
hash = perl_get_hv(
"Win32::GUI::Menus"
, FALSE);
itoa(nID, temp, 10);
handle = hv_fetch(hash, temp,
strlen
(temp), FALSE);
if
(handle == NULL)
return
NULL;
return
INT2PTR(
HMENU
,SvIV(*handle));
}
BOOL
GetMenuName(NOTXSPROC
HWND
hwnd,
int
nID,
char
*Name) {
MENUITEMINFO mii;
HMENU
hmenu;
LPPERLWIN32GUI_MENUITEMDATA perlmid;
ZeroMemory(&mii,
sizeof
(MENUITEMINFO));
mii.cbSize =
sizeof
(MENUITEMINFO);
mii.fMask = MIIM_DATA;
hmenu = GetMenu(hwnd);
if
(hmenu == NULL) hmenu = GetMenuFromID( NOTXSCALL nID );
if
(GetMenuItemInfo( hmenu, nID, 0, &mii ) == 0) {
hmenu = GetMenuFromID( NOTXSCALL nID );
}
if
(GetMenuItemInfo( hmenu, nID, 0, &mii )) {
perlmid = (LPPERLWIN32GUI_MENUITEMDATA) mii.dwItemData;
if
(perlmid != NULL && perlmid->dwSize ==
sizeof
(PERLWIN32GUI_MENUITEMDATA)) {
strcpy
(Name, perlmid->szName);
return
TRUE;
}
else
{
return
FALSE;
}
}
else
{
return
FALSE;
}
}
BOOL
GetAcceleratorName(NOTXSPROC
int
nID,
char
*Name) {
HV* hash;
SV** name;
char
temp[80];
hash = perl_get_hv(
"Win32::GUI::Accelerators"
, FALSE);
itoa(nID, temp, 10);
name = hv_fetch_mg(NOTXSCALL hash, temp,
strlen
(temp), FALSE);
if
(name == NULL)
return
FALSE;
strcpy
(Name, (
char
*) SvPV_nolen(*name));
return
TRUE;
}
BOOL
GetTimerName(NOTXSPROC
HWND
hwnd,
UINT
nID,
char
*Name) {
HV* parent;
SV** name;
SV** robjarray;
HV* objarray;
SV** robj;
HV* obj;
char
temp[80];
parent = HV_SELF_FROM_WINDOW(hwnd);
if
(parent == NULL)
return
FALSE;
itoa(nID, temp, 10);
robjarray = hv_fetch_mg(NOTXSCALL parent,
"-timers"
, 7, FALSE);
if
(robjarray == NULL)
return
FALSE;
objarray = (HV*) SvRV(*robjarray);
robj = hv_fetch_mg(NOTXSCALL objarray, temp,
strlen
(temp), FALSE);
if
(robj == NULL)
return
FALSE;
obj = (HV*) SvRV(*robj);
if
(obj == NULL)
return
FALSE;
name = hv_fetch_mg(NOTXSCALL obj,
"-name"
, 5, FALSE);
if
(name == NULL)
return
FALSE;
strcpy
(Name, (
char
*) SvPV_nolen(*name));
return
TRUE;
}
BOOL
GetNotifyIconName(NOTXSPROC
HWND
hwnd,
UINT
nID,
char
*Name) {
HV* parent;
SV** name;
SV** robjarray;
HV* objarray;
SV** robj;
HV* obj;
char
temp[80];
parent = HV_SELF_FROM_WINDOW(hwnd);
if
(parent == NULL)
return
FALSE;
itoa(nID, temp, 10);
robjarray = hv_fetch_mg(NOTXSCALL parent,
"-notifyicons"
, 12, FALSE);
if
(robjarray == NULL)
return
FALSE;
objarray = (HV*) SvRV(*robjarray);
robj = hv_fetch_mg(NOTXSCALL objarray, temp,
strlen
(temp), FALSE);
if
(robj == NULL)
return
FALSE;
obj = (HV*) SvRV(*robj);
name = hv_fetch_mg(NOTXSCALL obj,
"-name"
, 5, FALSE);
if
(name == NULL)
return
FALSE;
strcpy
(Name, (
char
*) SvPV_nolen(*name));
return
TRUE;
}
DWORD
CALLBACK RichEditSave(
DWORD_PTR
dwCookie,
LPBYTE
pbBuff,
LONG
cb,
LONG
FAR *pcb) {
HANDLE
hfile;
hfile = (
HANDLE
) dwCookie;
WriteFile(hfile, (
LPCVOID
) pbBuff, (
DWORD
) cb, (
LPDWORD
) pcb, NULL);
return
(0);
}
DWORD
CALLBACK RichEditLoad(
DWORD_PTR
dwCookie,
LPBYTE
pbBuff,
LONG
cb,
LONG
FAR *pcb) {
HANDLE
hfile;
hfile = (
HANDLE
) dwCookie;
ReadFile(hfile, (
LPVOID
) pbBuff, (
DWORD
) cb, (
LPDWORD
) pcb, NULL);
return
(0);
}
int
CALLBACK BrowseForFolderProc(
HWND
hWnd,
UINT
uMsg,
LPARAM
lParam,
LPARAM
lpData) {
UNREFERENCED_PARAMETER(lParam);
if
(uMsg == BFFM_INITIALIZED && lpData != 0) {
SendMessage(hWnd, BFFM_SETSELECTION, TRUE, lpData);
}
return
(0);
}
int
AdjustSplitterCoord(NOTXSPROC LPPERLWIN32GUI_USERDATA perlud,
int
x,
int
w,
HWND
phwnd) {
int
min, max;
int
adjusted;
RECT rc;
adjusted = x;
min = -1;
min = perlud->iMinWidth;
if
(min == -1) min = 0;
GetClientRect(phwnd, &rc);
max = -1;
max = perlud->iMaxWidth;
if
(max == -1) max = rc.right - w;
if
(adjusted < min) adjusted = min;
if
(adjusted > max) adjusted = max;
return
(adjusted);
}
void
DrawSplitter(NOTXSPROC
HWND
hwnd,
int
x,
int
y,
int
w,
int
h) {
static
WORD
_dotPatternBmp[8] = { 0x00aa, 0x0055, 0x00aa, 0x0055,
0x00aa, 0x0055, 0x00aa, 0x0055};
HDC
hdc;
HBITMAP
hbm;
HBRUSH
hbr, hbrushOld;
hbm = CreateBitmap(8, 8, 1, 1, _dotPatternBmp);
hbr = CreatePatternBrush(hbm);
hdc = GetDCEx(hwnd, NULL, DCX_PARENTCLIP);
SetBrushOrgEx(hdc, x, y, NULL);
hbrushOld = (
HBRUSH
)SelectObject(hdc, hbr);
PatBlt(hdc, x, y, w, h, PATINVERT);
SelectObject(hdc, hbrushOld);
ReleaseDC(hwnd, hdc);
DeleteObject(hbr);
DeleteObject(hbm);
}
BOOL
CALLBACK EnumMyWindowsProc(
HWND
hwnd,
LPARAM
lparam) {
dTHX;
AV* ary;
DWORD
pid;
ary = (AV*) lparam;
GetWindowThreadProcessId(hwnd, &pid);
if
(pid == GetCurrentProcessId()) {
av_push(ary, newSViv(PTR2IV(hwnd)));
}
return
TRUE;
}
BOOL
CALLBACK CountMyWindowsProc(
HWND
hwnd,
LPARAM
lparam) {
DWORD
pid;
DWORD
style;
int
* i;
i = (
int
*) lparam;
GetWindowThreadProcessId(hwnd, &pid);
if
(pid == GetCurrentProcessId()) {
style = (
DWORD
) GetWindowLongPtr(hwnd, GWL_STYLE);
if
(!(style & GW_CHILD)) {
*i += 1;
}
}
return
TRUE;
}
BOOL
CALLBACK EnableWindowsProc(
HWND
hwnd,
LPARAM
lParam) {
EnableWindow (hwnd, (
BOOL
) lParam);
return
TRUE;
}
BOOL
CALLBACK FindChildWindowsProc(
HWND
hwnd,
LPARAM
lParam) {
st_FindChildWindow * st = (st_FindChildWindow*) lParam;
LPPERLWIN32GUI_USERDATA perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if
( !ValidUserData(perlud) )
return
TRUE;
if
(
strcmp
(perlud->szWindowName, st->Name) == 0) {
st->perlchild = perlud;
return
FALSE;
}
return
TRUE;
}
LRESULT
CALLBACK WindowsHookMsgProc(
int
code,
WPARAM
wParam,
LPARAM
lParam) {
SV* perlsub;
SV** arrayref;
SV** arrayval;
AV* array;
MSG* pmsg;
LPPERLWIN32GUI_USERDATA perlud;
I32 count;
int
PerlResult;
int
i;
if
(code == MSGF_MENU) {
PerlResult = 1;
pmsg = (MSG *)lParam;
perlud = (LPPERLWIN32GUI_USERDATA) GetWindowLongPtr(pmsg->hwnd, GWLP_USERDATA);
if
(ValidUserData(perlud)) {
PERLUD_FETCH;
if
(perlud->avHooks != NULL) {
arrayref = av_fetch(perlud->avHooks, WM_TRACKPOPUP_MSGHOOK, 0);
if
(arrayref != NULL) {
array = (AV*) SvRV(*arrayref);
SvREFCNT_inc((SV*) array);
for
(i = 0; i <= (
int
) av_len(array); i++) {
arrayval = av_fetch(array,(I32) i,0);
if
(arrayval != NULL) {
perlsub = *arrayval;
SvREFCNT_inc(perlsub);
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(perlud->svSelf);
XPUSHs(sv_2mortal(newSViv(pmsg->message)));
XPUSHs(sv_2mortal(newSViv(pmsg->wParam)));
XPUSHs(sv_2mortal(newSViv(pmsg->lParam)));
PUTBACK;
count = call_sv(perlsub, G_ARRAY|G_EVAL);
SPAGAIN;
if
(SvTRUE(ERRSV)) {
ProcessEventError(NOTXSCALL
"TrackPopupMenu(WindowsHookMsgProc)"
, &PerlResult);
}
else
{
if
(count > 0) { PerlResult = POPi; }
}
PUTBACK;
FREETMPS;
LEAVE;
SvREFCNT_dec(perlsub);
}
}
SvREFCNT_dec((SV*) array);
if
(PerlResult == 0) {
return
1;
}
else
if
(PerlResult == -1) {
SendMessage(pmsg->hwnd, WM_CANCELMODE, 0, 0);
PostMessage(pmsg->hwnd, WM_EXITLOOP, (
WPARAM
) -1, 0);
return
1;
}
}
}
}
}
return
CallNextHookEx(0, code, wParam, lParam);
}