summaryrefslogtreecommitdiff
path: root/iup/src/win/iupwin_common.c
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2009-11-04 11:56:41 -0800
committerPixel <pixel@nobis-crew.org>2009-11-04 11:59:33 -0800
commitd577d991b97ae2b5ee1af23641bcffc3f83af5b2 (patch)
tree590639d50205d1bcfaff2a7d2dc6ebf3f373c7ed /iup/src/win/iupwin_common.c
Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux.
Diffstat (limited to 'iup/src/win/iupwin_common.c')
-rwxr-xr-xiup/src/win/iupwin_common.c865
1 files changed, 865 insertions, 0 deletions
diff --git a/iup/src/win/iupwin_common.c b/iup/src/win/iupwin_common.c
new file mode 100755
index 0000000..a1a7c0f
--- /dev/null
+++ b/iup/src/win/iupwin_common.c
@@ -0,0 +1,865 @@
+/** \file
+ * \brief Windows Base Procedure
+ *
+ * See Copyright Notice in "iup.h"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <windows.h>
+#include <commctrl.h>
+
+#include "iup.h"
+#include "iupcbs.h"
+
+#include "iup_object.h"
+#include "iup_childtree.h"
+#include "iup_key.h"
+#include "iup_str.h"
+#include "iup_class.h"
+#include "iup_attrib.h"
+#include "iup_focus.h"
+#include "iup_image.h"
+#include "iup_dialog.h"
+#include "iup_drvinfo.h"
+#include "iup_drv.h"
+
+#include "iupwin_drv.h"
+#include "iupwin_handle.h"
+#include "iupwin_brush.h"
+
+
+#ifndef XBUTTON1
+#define XBUTTON1 0x0001 /* not defined in MingW3 */
+#endif
+
+int iupwinClassExist(const char* name)
+{
+ WNDCLASS WndClass;
+ if (GetClassInfo(iupwin_hinstance, name, &WndClass))
+ return 1;
+ return 0;
+}
+
+int iupwinGetScreenRes(void)
+{
+ int res;
+ HDC ScreenDC = GetDC(NULL);
+ res = GetDeviceCaps(ScreenDC, LOGPIXELSY);
+ ReleaseDC(NULL, ScreenDC);
+ return res;
+}
+
+void iupdrvActivate(Ihandle* ih)
+{
+ /* do not use BM_CLICK because it changes the focus
+ and does not animates the button press */
+ SendMessage(ih->handle, BM_SETSTATE, TRUE, 0);
+ IupFlush();
+ Sleep(150);
+ SendMessage(GetParent(ih->handle), WM_COMMAND, MAKEWPARAM(0, BN_CLICKED), (LPARAM)ih->handle);
+ SendMessage(ih->handle, BM_SETSTATE, FALSE, 0);
+}
+
+WCHAR* iupwinStrChar2Wide(const char* str)
+{
+ if (str)
+ {
+ int len = strlen(str)+1;
+ WCHAR* wstr = malloc(len * sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, len);
+ return wstr;
+ }
+
+ return NULL;
+}
+
+int iupdrvGetScrollbarSize(void)
+{
+ int xv = GetSystemMetrics(SM_CXVSCROLL);
+ int yh = GetSystemMetrics(SM_CYHSCROLL);
+ return xv > yh ? xv : yh;
+}
+
+void iupdrvReparent(Ihandle* ih)
+{
+ SetParent(ih->handle, iupChildTreeGetNativeParentHandle(ih));
+}
+
+void iupdrvBaseLayoutUpdateMethod(Ihandle *ih)
+{
+ SetWindowPos(ih->handle, NULL, ih->x, ih->y, ih->currentwidth, ih->currentheight,
+ SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER);
+}
+
+void iupdrvDisplayRedraw(Ihandle *ih)
+{
+ /* REDRAW Now */
+ RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_NOCHILDREN|RDW_UPDATENOW);
+}
+
+void iupdrvDisplayUpdate(Ihandle *ih)
+{
+ /* Post a REDRAW */
+ RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_NOCHILDREN);
+}
+
+void iupdrvScreenToClient(Ihandle* ih, int *x, int *y)
+{
+ POINT p;
+ p.x = *x;
+ p.y = *y;
+ ScreenToClient(ih->handle, &p);
+ *x = p.x;
+ *y = p.y;
+}
+
+static void winTrackMouse(HWND hwnd, int enter)
+{
+ TRACKMOUSEEVENT mouse;
+ mouse.cbSize = sizeof(TRACKMOUSEEVENT);
+
+ if (enter)
+ mouse.dwFlags = TME_HOVER;
+ else
+ mouse.dwFlags = TME_LEAVE;
+
+ mouse.hwndTrack = hwnd;
+ mouse.dwHoverTime = 1;
+ TrackMouseEvent(&mouse);
+}
+
+static void winCallEnterLeaveWindow(Ihandle *ih, int enter)
+{
+ Icallback cb = NULL;
+
+ if (!ih->iclass->is_interactive)
+ return;
+
+ if (enter)
+ {
+ winTrackMouse(ih->handle, 0);
+
+ if (!iupAttribGetInt(ih, "_IUPWIN_ENTERWIN"))
+ {
+ cb = IupGetCallback(ih,"ENTERWINDOW_CB");
+ iupAttribSetStr(ih, "_IUPWIN_ENTERWIN", "1");
+ }
+ }
+ else
+ {
+ cb = IupGetCallback(ih,"LEAVEWINDOW_CB");
+ iupAttribSetStr(ih, "_IUPWIN_ENTERWIN", NULL);
+ }
+
+ if (cb)
+ cb(ih);
+}
+
+void iupwinMergeStyle(Ihandle* ih, DWORD old_mask, DWORD value)
+{
+ DWORD dwStyle = GetWindowLong(ih->handle, GWL_STYLE);
+ dwStyle &= ~(old_mask); /* clear old bits */
+ dwStyle |= value;
+ SetWindowLong(ih->handle, GWL_STYLE, dwStyle);
+}
+
+void iupwinSetStyle(Ihandle* ih, DWORD value, int set)
+{
+ DWORD dwStyle = GetWindowLong(ih->handle, GWL_STYLE);
+ if (set)
+ dwStyle |= value;
+ else
+ dwStyle &= ~(value);
+ SetWindowLong(ih->handle, GWL_STYLE, dwStyle);
+}
+
+int iupwinBaseProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result)
+{
+ (void)lp;
+
+ switch (msg)
+ {
+ case WM_GETDLGCODE:
+ {
+ *result = DLGC_WANTALLKEYS;
+ return 1;
+ }
+ case WM_NOTIFY: /* usually sent only to parent,
+ but TIPs are configured to be handled here */
+ {
+ NMHDR* msg_info = (NMHDR*)lp;
+ if (msg_info->code == TTN_GETDISPINFO)
+ iupwinTipsGetDispInfo(lp);
+ break;
+ }
+ case WM_DROPFILES:
+ iupwinDropFiles((HDROP)wp, ih);
+ break;
+ case WM_HELP:
+ {
+ Ihandle* child;
+ HELPINFO* help_info = (HELPINFO*)lp;
+
+ if (help_info->iContextType == HELPINFO_MENUITEM)
+ child = iupwinMenuGetItemHandle((HMENU)help_info->hItemHandle, (int)help_info->iCtrlId);
+ else
+ child = iupwinHandleGet(help_info->hItemHandle);
+
+ if (child)
+ {
+ Icallback cb = (Icallback) IupGetCallback(child, "HELP_CB");
+ if (cb)
+ {
+ if (cb(child) == IUP_CLOSE)
+ IupExitLoop();
+
+ *result = 0;
+ return 1; /* abort default processing */
+ }
+ }
+ break;
+ }
+ case WM_MOUSELEAVE:
+ winCallEnterLeaveWindow(ih, 0);
+ break;
+ case WM_MOUSEMOVE:
+ winCallEnterLeaveWindow(ih, 1);
+ break;
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ if (!iupwinKeyEvent(ih, (int)wp, 1))
+ {
+ *result = 0;
+ return 1; /* abort default processing */
+ }
+ break;
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ {
+ int ret;
+ if (wp == VK_SNAPSHOT) /* called only on key up */
+ {
+ ret = iupwinKeyEvent(ih, (int)wp, 1);
+ if (ret && iupObjectCheck(ih))
+ ret = iupwinKeyEvent(ih, (int)wp, 0);
+ }
+ else
+ ret = iupwinKeyEvent(ih, (int)wp, 0);
+
+ if (!ret)
+ {
+ *result = 0;
+ return 1; /* abort default processing */
+ }
+
+ break;
+ }
+ case WM_SETFOCUS:
+ iupwinWmSetFocus(ih);
+ break;
+ case WM_KILLFOCUS:
+ iupCallKillFocusCb(ih);
+ break;
+ case WOM_CLOSE:
+ case WOM_DONE:
+ case WOM_OPEN:
+ {
+ IFni cb = (IFni)IupGetCallback(ih, "WOM_CB");
+ if (cb)
+ {
+ int v = -2; /* Error */
+ switch(msg)
+ {
+ case WOM_OPEN: v = 1; break;
+ case WOM_DONE: v = 0; break;
+ case WOM_CLOSE: v = -1; break;
+ }
+ cb(ih, v);
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+LRESULT CALLBACK iupwinBaseWinProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+ int ret = 0;
+ LRESULT result = 0;
+ IwinProc winProc;
+ WNDPROC oldProc;
+ Ihandle *ih;
+
+ ih = iupwinHandleGet(hwnd);
+ if (!ih)
+ return DefWindowProc(hwnd, msg, wp, lp); /* should never happen */
+
+ /* retrieve the control previous procedure for subclassing */
+ oldProc = (WNDPROC)IupGetCallback(ih, "_IUPWIN_OLDPROC_CB");
+
+ /* check if the element defines a custom procedure */
+ winProc = (IwinProc)IupGetCallback(ih, "_IUPWIN_CTRLPROC_CB");
+ if (winProc)
+ ret = winProc(ih, msg, wp, lp, &result);
+ else
+ ret = iupwinBaseProc(ih, msg, wp, lp, &result);
+
+ if (ret)
+ return result;
+ else
+ return CallWindowProc(oldProc, hwnd, msg, wp, lp);
+}
+
+static Ihandle* winContainerWmCommandGetIhandle(Ihandle *ih, WPARAM wp, LPARAM lp)
+{
+ /* WPARAM - if HIWORD is 0 if the message is from a menu.
+ or HIWORD is 1 if the message is from an accelerator.
+ or HIWORD is the notification code if the message is from a control.
+ LOWORD is the identifier.
+ LPARAM - the control sending the message or 0. */
+
+ Ihandle *child = NULL;
+
+ if (HIWORD(wp)==0 && lp==0 && LOWORD(wp)>10)
+ {
+ Ihandle* dlg_menu = IupGetAttributeHandle(ih, "MENU");
+ if (dlg_menu)
+ child = iupwinMenuGetItemHandle((HMENU)dlg_menu->handle, LOWORD(wp)); /* menu */
+ }
+ else
+ {
+ if (lp==0)
+ child = ih; /* native parent */
+ else
+ {
+ child = iupwinHandleGet((void*)lp); /* control */
+ if (!child)
+ child = iupwinHandleGet((void*)GetParent((HWND)lp)); /* control */
+ }
+ }
+
+ return child;
+}
+
+int iupwinBaseContainerProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result)
+{
+ /* All messages here are sent to the parent Window,
+ but they are usefull for child controls. */
+
+ switch (msg)
+ {
+ case WM_COMMAND:
+ {
+ Ihandle* child = winContainerWmCommandGetIhandle(ih, wp, lp);
+ if (child)
+ {
+ IFnii cb = (IFnii)IupGetCallback(child, "_IUPWIN_COMMAND_CB");
+ if (cb)
+ cb(child, wp, lp);
+ }
+
+ break;
+ }
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ {
+ Ihandle* child = iupwinHandleGet((void*)lp);
+ if (child)
+ {
+ IFctlColor cb = (IFctlColor)IupGetCallback(child, "_IUPWIN_CTLCOLOR_CB");
+ if (cb)
+ return cb(child, (HDC)wp, result);
+ }
+ break;
+ }
+ case WM_DRAWITEM: /* for OWNERDRAW controls */
+ {
+ Ihandle *child = NULL;
+ DRAWITEMSTRUCT *drawitem = (LPDRAWITEMSTRUCT)lp;
+ if (!drawitem)
+ break;
+
+ if (wp == 0) /* a menu */
+ child = iupwinMenuGetItemHandle((HMENU)drawitem->hwndItem, drawitem->itemID);
+ else
+ child = iupwinHandleGet(drawitem->hwndItem);
+
+ if (child)
+ {
+ IFdrawItem cb = (IFdrawItem)IupGetCallback(child, "_IUPWIN_DRAWITEM_CB");
+ if (cb)
+ {
+ cb(child, (void*)drawitem);
+ *result = TRUE;
+ return 1;
+ }
+ }
+ break;
+ }
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ {
+ Ihandle *child = iupwinHandleGet((void*)lp);
+ if (child)
+ {
+ IFni cb = (IFni)IupGetCallback(child, "_IUPWIN_CUSTOMSCROLL_CB");
+ if (cb)
+ cb(child, LOWORD(wp));
+ }
+ break;
+ }
+ case WM_NOTIFY: /* Currently, the following controls support custom draw functionality:
+ Header, List-view, Rebar, Toolbar, ToolTip, Trackbar, Tree-view.
+ And for Button if using Windows XP Style. */
+ {
+ Ihandle *child;
+ NMHDR* msg_info = (NMHDR*)lp;
+ if (!msg_info)
+ break;
+
+ child = iupwinHandleGet(msg_info->hwndFrom);
+ if (child)
+ {
+ IFnotify cb = (IFnotify)IupGetCallback(child, "_IUPWIN_NOTIFY_CB");
+ if (cb)
+ {
+ if (cb(child, (void*)msg_info, result))
+ return 1;
+ }
+ }
+ break;
+ }
+ }
+
+ return iupwinBaseProc(ih, msg, wp, lp, result);
+}
+
+void iupwinChangeProc(Ihandle *ih, WNDPROC new_proc)
+{
+ IupSetCallback(ih, "_IUPWIN_OLDPROC_CB", (Icallback)GetWindowLongPtr(ih->handle, GWLP_WNDPROC));
+ SetWindowLongPtr(ih->handle, GWLP_WNDPROC, (LONG_PTR)new_proc);
+}
+
+void iupdrvBaseUnMapMethod(Ihandle* ih)
+{
+ WNDPROC oldProc = (WNDPROC)IupGetCallback(ih, "_IUPWIN_OLDPROC_CB");
+ if (oldProc)
+ {
+ SetWindowLongPtr(ih->handle, GWLP_WNDPROC, (LONG_PTR)oldProc);
+ IupSetCallback(ih, "_IUPWIN_OLDPROC_CB", NULL);
+ }
+
+ /* remove the association before destroying */
+ iupwinHandleRemove(ih);
+
+ /* destroys window (it will remove from parent) */
+ DestroyWindow(ih->handle);
+}
+
+void iupwinDropFiles(HDROP hDrop, Ihandle *ih)
+{
+ char *filename;
+ int i, numFiles, numchar, ret;
+ POINT point;
+
+ IFnsiii cb = (IFnsiii)IupGetCallback(ih, "DROPFILES_CB");
+ if (!cb) return;
+
+ numFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
+ DragQueryPoint(hDrop, &point);
+ for (i = 0; i < numFiles; i++)
+ {
+ numchar = DragQueryFile(hDrop, i, NULL, 0);
+ filename = malloc(numchar+1);
+ if (!filename)
+ break;
+
+ DragQueryFile(hDrop, i, filename, numchar+1);
+
+ ret = cb(ih, filename, numFiles-i-1, (int) point.x, (int) point.y);
+
+ free(filename);
+
+ if (ret == IUP_IGNORE)
+ break;
+ }
+ DragFinish(hDrop);
+}
+
+int iupwinGetColorRef(Ihandle *ih, char *name, COLORREF *color)
+{
+ unsigned char r, g, b;
+ /* must use IupGetAttribute to use inheritance */
+ if (iupStrToRGB(IupGetAttribute(ih, name), &r, &g, &b))
+ {
+ *color = RGB(r,g,b);
+ return 1;
+ }
+ return 0;
+}
+
+int iupwinGetParentBgColor(Ihandle* ih, COLORREF* cr)
+{
+ unsigned char r, g, b;
+ char* color = iupBaseNativeParentGetBgColorAttrib(ih);
+ if (iupStrToRGB(color, &r, &g, &b))
+ {
+ *cr = RGB(r,g,b);
+ return 1;
+ }
+ return 0;
+}
+
+int iupdrvBaseSetZorderAttrib(Ihandle* ih, const char* value)
+{
+ if (IsWindowVisible(ih->handle))
+ {
+ if (iupStrEqualNoCase(value, "TOP"))
+ SetWindowPos(ih->handle, HWND_TOP, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
+ else
+ SetWindowPos(ih->handle, HWND_BOTTOM, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
+ }
+
+ return 0;
+}
+
+void iupdrvSetVisible(Ihandle* ih, int visible)
+{
+ ShowWindow(ih->handle, visible? SW_SHOWNORMAL: SW_HIDE);
+}
+
+int iupdrvIsVisible(Ihandle* ih)
+{
+ return IsWindowVisible(ih->handle);
+}
+
+int iupdrvIsActive(Ihandle* ih)
+{
+ return IsWindowEnabled(ih->handle);
+}
+
+void iupdrvSetActive(Ihandle* ih, int enable)
+{
+ EnableWindow(ih->handle, enable);
+}
+
+int iupdrvBaseSetTitleAttrib(Ihandle* ih, const char* value)
+{
+ if (!value) value = "";
+ SetWindowText(ih->handle, value);
+ return 0;
+}
+
+char* iupdrvBaseGetTitleAttrib(Ihandle* ih)
+{
+ int nc = GetWindowTextLength(ih->handle);
+ if (nc)
+ {
+ char* str = iupStrGetMemory(nc+1);
+ GetWindowText(ih->handle, str, nc+1);
+ return str;
+ }
+ else
+ return NULL;
+}
+
+int iupwinSetDragDropAttrib(Ihandle* ih, const char* value)
+{
+ if (iupStrBoolean(value))
+ DragAcceptFiles(ih->handle, TRUE);
+ else
+ DragAcceptFiles(ih->handle, FALSE);
+ return 1;
+}
+
+char *iupdrvBaseGetXAttrib(Ihandle *ih)
+{
+ char* str = iupStrGetMemory(20);
+ RECT rect;
+ GetWindowRect(ih->handle, &rect);
+ sprintf(str, "%d", (int)rect.left);
+ return str;
+}
+
+char *iupdrvBaseGetYAttrib(Ihandle *ih)
+{
+ char* str = iupStrGetMemory(20);
+ RECT rect;
+ GetWindowRect(ih->handle, &rect);
+ sprintf(str, "%d", (int)rect.top);
+ return str;
+}
+
+char* iupdrvBaseGetClientSizeAttrib(Ihandle* ih)
+{
+ char* str = iupStrGetMemory(20);
+ RECT rect;
+ GetClientRect(ih->handle, &rect);
+ sprintf(str, "%dx%d", (int)(rect.right-rect.left), (int)(rect.bottom-rect.top));
+ return str;
+}
+
+#ifndef IDC_HAND
+#define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+#ifndef IDC_APPSTARTING
+#define IDC_APPSTARTING MAKEINTRESOURCE(32650)
+#endif
+#ifndef IDC_HELP
+#define IDC_HELP MAKEINTRESOURCE(32651)
+#endif
+
+static HCURSOR winGetCursor(Ihandle* ih, const char* name)
+{
+ static struct {
+ const char* iupname;
+ const char* sysname;
+ } table[] = {
+ {"NONE", NULL},
+ {"NULL", NULL},
+ {"ARROW", IDC_ARROW},
+ {"BUSY", IDC_WAIT},
+ {"CROSS", IDC_CROSS},
+ {"HAND", IDC_HAND},
+ {"MOVE", IDC_SIZEALL},
+ {"RESIZE_N", IDC_SIZENS},
+ {"RESIZE_S", IDC_SIZENS},
+ {"RESIZE_NS", IDC_SIZENS},
+ {"RESIZE_W", IDC_SIZEWE},
+ {"RESIZE_E", IDC_SIZEWE},
+ {"RESIZE_WE", IDC_SIZEWE},
+ {"RESIZE_NE", IDC_SIZENESW},
+ {"RESIZE_SE", IDC_SIZENWSE},
+ {"RESIZE_NW", IDC_SIZENWSE},
+ {"RESIZE_SW", IDC_SIZENESW},
+ {"TEXT", IDC_IBEAM},
+ {"HELP", IDC_HELP},
+ {"IUP", IDC_HELP},
+ {"NO", IDC_NO},
+ {"UPARROW", IDC_UPARROW},
+ {"APPSTARTING", IDC_APPSTARTING}
+ };
+
+ HCURSOR cur;
+ char str[50];
+ int i, count = sizeof(table)/sizeof(table[0]);
+
+ /* check the cursor cache first (per control)*/
+ sprintf(str, "_IUPWIN_CURSOR_%s", name);
+ cur = (HCURSOR)iupAttribGet(ih, str);
+ if (cur)
+ return cur;
+
+ /* check the pre-defined IUP names first */
+ for (i = 0; i < count; i++)
+ {
+ if (iupStrEqualNoCase(name, table[i].iupname))
+ {
+ if (table[i].sysname)
+ cur = LoadCursor(NULL, table[i].sysname);
+ else
+ cur = NULL;
+
+ break;
+ }
+ }
+
+ if (i == count)
+ {
+ /* check other system cursors */
+ /* cursor PEN is handled here */
+ if (iupStrEqualNoCase(name, "PEN"))
+ name = "CURSOR_PEN";
+
+ /* check for an name defined cursor */
+ cur = iupImageGetCursor(name);
+ }
+
+ iupAttribSetStr(ih, str, (char*)cur);
+ return cur;
+}
+
+int iupdrvBaseSetCursorAttrib(Ihandle* ih, const char* value)
+{
+ /* Cursor can be NULL in Windows. */
+ HCURSOR hCur = winGetCursor(ih, value);
+ iupAttribSetStr(ih, "_IUPWIN_HCURSOR", (char*)hCur); /* To be used in WM_SETCURSOR */
+ /* refresh the cursor */
+ SendMessage(ih->handle, WM_SETCURSOR, (WPARAM)ih->handle, MAKELPARAM(1,WM_MOUSEMOVE));
+ return 1;
+}
+
+void iupdrvBaseRegisterCommonAttrib(Iclass* ic)
+{
+ iupClassRegisterAttribute(ic, "HFONT", iupwinGetHFontAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+}
+
+int iupwinButtonDown(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp)
+{
+ char status[IUPKEY_STATUS_SIZE] = IUPKEY_STATUS_INIT;
+ int ret, doubleclick = 0;
+ int b = 0;
+
+ IFniiiis cb = (IFniiiis) IupGetCallback(ih, "BUTTON_CB");
+ if (!cb)
+ return 0;
+
+ if (msg==WM_XBUTTONDBLCLK ||
+ msg==WM_LBUTTONDBLCLK ||
+ msg==WM_MBUTTONDBLCLK ||
+ msg==WM_RBUTTONDBLCLK)
+ doubleclick = 1;
+
+ iupwinButtonKeySetStatus(LOWORD(wp), status, doubleclick);
+
+ if (msg==WM_LBUTTONDOWN || msg==WM_LBUTTONDBLCLK)
+ b = IUP_BUTTON1;
+ else if (msg==WM_MBUTTONDOWN || msg==WM_MBUTTONDBLCLK)
+ b = IUP_BUTTON2;
+ else if (msg==WM_RBUTTONDOWN || msg==WM_RBUTTONDBLCLK)
+ b = IUP_BUTTON3;
+ else if (msg==WM_XBUTTONDOWN || msg==WM_XBUTTONDBLCLK)
+ {
+ if (HIWORD(wp) == XBUTTON1)
+ b = IUP_BUTTON4;
+ else
+ b = IUP_BUTTON5;
+ }
+
+ ret = cb(ih, b, 1, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp), status);
+ if (ret == IUP_CLOSE)
+ IupExitLoop();
+ else if (ret == IUP_IGNORE)
+ return -1;
+
+ return 1;
+}
+
+int iupwinButtonUp(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp)
+{
+ char status[IUPKEY_STATUS_SIZE] = IUPKEY_STATUS_INIT;
+ int ret, b=0;
+ IFniiiis cb = (IFniiiis) IupGetCallback(ih, "BUTTON_CB");
+ if (!cb)
+ return 0;
+
+ iupwinButtonKeySetStatus(LOWORD(wp), status, 0);
+
+ /* also updates the button status, since wp could not have the flag */
+ if (msg==WM_LBUTTONUP)
+ {
+ b = IUP_BUTTON1;
+ iupKEYSETBUTTON1(status);
+ }
+ else if (msg==WM_MBUTTONUP)
+ {
+ b = IUP_BUTTON2;
+ iupKEYSETBUTTON2(status);
+ }
+ else if (msg==WM_RBUTTONUP)
+ {
+ b = IUP_BUTTON3;
+ iupKEYSETBUTTON3(status);
+ }
+ else if (msg==WM_XBUTTONUP)
+ {
+ if (HIWORD(wp) == XBUTTON1)
+ {
+ b = IUP_BUTTON4;
+ iupKEYSETBUTTON4(status);
+ }
+ else
+ {
+ b = IUP_BUTTON5;
+ iupKEYSETBUTTON5(status);
+ }
+ }
+
+ ret = cb(ih, b, 0, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp), status);
+ if (ret == IUP_CLOSE)
+ IupExitLoop();
+ else if (ret == IUP_IGNORE)
+ return -1;
+
+ return 1;
+}
+
+int iupwinMouseMove(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp)
+{
+ IFniis cb = (IFniis)IupGetCallback(ih, "MOTION_CB");
+ if (cb)
+ {
+ char status[IUPKEY_STATUS_SIZE] = IUPKEY_STATUS_INIT;
+ iupwinButtonKeySetStatus(LOWORD(wp), status, 0);
+ cb(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp), status);
+ return 1;
+ }
+ (void)msg;
+ return 0;
+}
+
+int iupwinCreateWindowEx(Ihandle* ih, LPCSTR lpClassName, DWORD dwExStyle, DWORD dwStyle)
+{
+ ih->serial = iupDialogGetChildId(ih);
+
+ ih->handle = CreateWindowEx(dwExStyle, /* extended window style */
+ lpClassName, /* window class */
+ NULL, /* title */
+ dwStyle, /* window style */
+ 0, /* x-position */
+ 0, /* y-position */
+ 10, /* default width to avoid 0 */
+ 10, /* default height to avoid 0 */
+ iupChildTreeGetNativeParentHandle(ih), /* window parent */
+ (HMENU)ih->serial, /* child identifier */
+ iupwin_hinstance, /* instance of app. */
+ NULL);
+
+ if (!ih->handle)
+ return 0;
+
+ /* associate HWND with Ihandle*, all Win32 controls must call this. */
+ iupwinHandleSet(ih);
+
+ /* replace the WinProc to handle base callbacks */
+ iupwinChangeProc(ih, iupwinBaseWinProc);
+
+ return 1;
+}
+
+char* iupwinGetClipboardText(Ihandle* ih)
+{
+ HANDLE Handle;
+ char* str;
+
+ if (!IsClipboardFormatAvailable(CF_TEXT))
+ return NULL;
+
+ if (!OpenClipboard(ih->handle))
+ return NULL;
+
+ Handle = GetClipboardData(CF_TEXT);
+ if (!Handle)
+ {
+ CloseClipboard();
+ return NULL;
+ }
+
+ str = (char*)GlobalLock(Handle);
+ str = iupStrDup(str);
+
+ GlobalUnlock(Handle);
+
+ CloseClipboard();
+
+ return str;
+}