changeset 634:c6a216c8174f

Support for setting transparent colour for bitmaps Support for checkable menu items Mouse support on render window Fix bubble text on buttons dw_window_set_text() works for group box dw_window_set_size() and dw_window_set_pos_size() to allow negative values Add dw_draw_polygon()
author mhessling@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 10 Apr 2009 10:25:26 +0000
parents 87db549e79bc
children 6cec85b90635
files dw.def dw.h dwtest.c dww-mingw.def dww.def makefile.vc win/dw.c
diffstat 7 files changed, 509 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/dw.def	Tue Jan 06 11:00:15 2009 +0000
+++ b/dw.def	Fri Apr 10 10:25:26 2009 +0000
@@ -62,10 +62,12 @@
   dw_window_redraw                       @79
 
   dw_bitmap_new                          @80
+  dw_window_set_bitmap_from_data         @81
 
   dw_button_new                          @90
   dw_bitmapbutton_new                    @91
   dw_bitmapbutton_new_from_file          @92
+  dw_bitmapbutton_new_from_data          @93
 
   dw_text_new                            @100
   dw_status_text_new                     @101
@@ -120,6 +122,7 @@
   dw_icon_load                           @210
   dw_icon_free                           @211
   dw_icon_load_from_file                 @212
+  dw_icon_load_from_data                 @213
 
   dw_container_new                       @220
   dw_container_setup                     @221
@@ -194,12 +197,15 @@
   dw_draw_line                           @332
   dw_draw_rect                           @333
   dw_draw_text                           @334
+  dw_draw_polygon                        @335
 
   dw_pixmap_bitblt                       @340
   dw_pixmap_new                          @341
   dw_pixmap_grab                         @342
   dw_pixmap_destroy                      @343
   dw_pixmap_new_from_file                @344
+  dw_pixmap_new_from_data                @345
+  dw_pixmap_set_transparent_color        @346
 
   dw_dialog_new                          @350
   dw_dialog_dismiss                      @351
@@ -271,3 +277,8 @@
   dw_calendar_new                        @480
   dw_calendar_set_date                   @481
   dw_calendar_get_date                   @482
+
+
+  dw_clipboard_get_text                  @490
+  dw_clipboard_set_text                  @491
+
--- a/dw.h	Tue Jan 06 11:00:15 2009 +0000
+++ b/dw.h	Fri Apr 10 10:25:26 2009 +0000
@@ -55,7 +55,14 @@
 #define DW_MIS_CHECKED           (1 << 2)
 #define DW_MIS_UNCHECKED         (1 << 3)
 
-#if defined(__OS2__) || defined(__WIN32__) || defined(__MAC__) || defined(WINNT) || defined(__EMX__)
+/* ensure we can build the Gtk port with MingW on Windows */
+#if defined(DW_USE_GTK) && defined(__MINGW32__)
+# ifndef GDK_WINDOWING_WIN32
+#   define GDK_WINDOWING_WIN32
+# endif
+#endif
+
+#if defined(__OS2__) || (defined(__WIN32__) && !defined(GDK_WINDOWING_WIN32)) || defined(__MAC__) || (defined(WINNT) && !defined(GDK_WINDOWING_WIN32)) || defined(__EMX__)
 /* OS/2, Windows or MacOS */
 
 #if (defined(__IBMC__) || defined(_System)) && !defined(API)
@@ -586,6 +593,7 @@
 	unsigned long width, height;
 	HBITMAP hbm;
 	HDC hdc;
+	unsigned long transcolor;
 	HWND handle;
 	void *bits;
 } *HPIXMAP;
@@ -656,11 +664,17 @@
 #else
 /* GTK Specific section */
 #include <gtk/gtk.h>
-#include <gdk/gdkx.h>
+#ifdef GDK_WINDOWING_X11
+# include <gdk/gdkx.h>
+#else
+# include <gdk/gdk.h>
+#endif
 #include <gdk/gdkprivate.h>
 #include <gdk/gdkkeysyms.h>
 #include <pthread.h>
-#include <dlfcn.h>
+#if !defined(GDK_WINDOWING_WIN32)
+# include <dlfcn.h>
+#endif
 
 #define DW_DT_LEFT               1
 #define DW_DT_UNDERSCORE         (1 << 1)
@@ -898,7 +912,7 @@
 typedef CTIME *PCTIME;
 #endif
 
-#if defined(__OS2__) || defined(__WIN32__) || defined(WINNT) || defined(__EMX__)
+#if defined(__OS2__) || (defined(__WIN32__) && !defined(GDK_WINDOWING_WIN32)) || (defined(WINNT) && !defined(GDK_WINDOWING_WIN32)) || defined(__EMX__)
 typedef unsigned long DWTID;
 #endif
 
@@ -1035,6 +1049,9 @@
 int API dw_window_set_color(HWND handle, unsigned long fore, unsigned long back);
 HWND API dw_window_new(HWND hwndOwner, char *title, unsigned long flStyle);
 HWND API dw_box_new(int type, int pad);
+#ifdef INCOMPLETE
+HWND API dw_scrollbox_new(int type, int pad);
+#endif
 HWND API dw_groupbox_new(int type, int pad, char *title);
 HWND API dw_mdi_new(unsigned long id);
 HWND API dw_bitmap_new(unsigned long id);
@@ -1074,10 +1091,10 @@
 unsigned int API dw_scrollbar_get_pos(HWND handle);
 void API dw_scrollbar_set_pos(HWND handle, unsigned int position);
 void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible);
-void API dw_window_set_pos(HWND handle, unsigned long x, unsigned long y);
+void API dw_window_set_pos(HWND handle, long x, long y);
 void API dw_window_set_size(HWND handle, unsigned long width, unsigned long height);
-void API dw_window_set_pos_size(HWND handle, unsigned long x, unsigned long y, unsigned long width, unsigned long height);
-void API dw_window_get_pos_size(HWND handle, unsigned long *x, unsigned long *y, unsigned long *width, unsigned long *height);
+void API dw_window_set_pos_size(HWND handle, long x, long y, unsigned long width, unsigned long height);
+void API dw_window_get_pos_size(HWND handle, long *x, long *y, unsigned long *width, unsigned long *height);
 void API dw_window_set_style(HWND handle, unsigned long style, unsigned long mask);
 void API dw_window_set_icon(HWND handle, unsigned long id);
 void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename);
@@ -1168,8 +1185,7 @@
 HMENUI API dw_menu_new(unsigned long id);
 HMENUI API dw_menubar_new(HWND location);
 HWND API dw_menu_append_item(HMENUI menu, char *title, unsigned long id, unsigned long flags, int end, int check, HMENUI submenu);
-#if 0
-TBD
+#ifdef INCOMPLETE
 void API dw_menu_delete_item(HMENUI menu, unsigned long id);
 #endif
 void API dw_menu_item_set_check(HMENUI menu, unsigned long id, int check);
@@ -1209,6 +1225,7 @@
 HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename);
 HPIXMAP API dw_pixmap_new_from_data(HWND handle, char *data, int len);
 HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id);
+void API dw_pixmap_set_transparent_color( HPIXMAP pixmap, ULONG color );
 void API dw_pixmap_destroy(HPIXMAP pixmap);
 void API dw_beep(int freq, int dur);
 int API dw_messagebox(char *title, int flags, char *format, ...);
--- a/dwtest.c	Tue Jan 06 11:00:15 2009 +0000
+++ b/dwtest.c	Fri Apr 10 10:25:26 2009 +0000
@@ -126,6 +126,7 @@
    textbox1, textbox2, textboxA,
    gap_box,
    buttonbox,
+   buttonsbox,
    buttonboxperm,
    cal,
    filetoolbarbox;
@@ -480,14 +481,32 @@
 int DWSIGNAL redraw_button_box_callback(HWND window, void *data)
 {
 #if 0
+
+   long x, y, width, height;
+   dw_window_get_pos_size(filetoolbarbox , &x, &y, &width, &height);
    dw_window_destroy( filetoolbarbox );
    create_button(1);
+   dw_window_set_pos_size(filetoolbarbox, x, y, width, height);
 #else
    dw_window_enable( window);
+   dw_menu_delete_item( changeable_menu, NONCHECKABLE_MENUITEMID );
 #endif
    return 0;
 }
 
+int DWSIGNAL change_color_red_callback(HWND window, void *data)
+{
+   dw_window_set_color(buttonsbox, DW_CLR_RED, DW_CLR_RED);
+   return 0;
+}
+
+int DWSIGNAL change_color_yellow_callback(HWND window, void *data)
+{
+   dw_window_set_color(buttonsbox, DW_CLR_YELLOW, DW_CLR_YELLOW);
+   return 0;
+}
+
+
 /* Callback to handle user selection of the scrollbar position */
 void DWSIGNAL scrollbar_valuechanged_callback(HWND hwnd, int value, void *data)
 {
@@ -902,12 +921,13 @@
 
 void buttons_add(void)
 {
-   HWND buttonsbox,abutton1,abutton2,calbox,bw;
+   HWND abutton1,abutton2,calbox,bw;
    int i;
    char buf[20];
    char **text;
 
    /* create a box to pack into the notebook page */
+// buttonsbox = dw_scrollbox_new(BOXVERT, 2);
    buttonsbox = dw_box_new(BOXVERT, 2);
    dw_box_pack_start( notebookbox5, buttonsbox, 25, 200, TRUE, TRUE, 0);
    dw_window_set_color(buttonsbox, DW_CLR_RED, DW_CLR_RED);
@@ -925,7 +945,8 @@
    buttonboxperm = dw_box_new( BOXVERT, 0 );
    dw_box_pack_start( buttonsbox, buttonboxperm, 25, 0, FALSE, TRUE, 2 );
    dw_window_set_color(buttonboxperm, DW_CLR_WHITE, DW_CLR_WHITE);
-   abutton1 = dw_bitmapbutton_new_from_file( "Top Button", 0, FILE_ICON_NAME );
+//   abutton1 = dw_bitmapbutton_new_from_file( "Top Button", 0, FILE_ICON_NAME );
+   abutton1 = dw_bitmapbutton_new_from_file( "Top Button", 0, "z:\\projects\\RexxGd\\regina\\tile_up.png" );
    dw_box_pack_start( buttonboxperm, abutton1, 100, 30, FALSE, FALSE, 0 );
    dw_signal_connect( abutton1, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(button_callback), NULL );
    dw_box_pack_start( buttonboxperm, 0, 25, 5, FALSE, FALSE, 0 );
@@ -996,12 +1017,12 @@
 
    abutton1 = dw_bitmapbutton_new_from_file( "Should be under Top button", 0, "junk" );
    dw_box_pack_start( filetoolbarbox, abutton1, 25, 25, FALSE, FALSE, 0);
-   dw_signal_connect( abutton1, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(redraw_button_box_callback), NULL );
+   dw_signal_connect( abutton1, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(change_color_red_callback), NULL );
    dw_box_pack_start( filetoolbarbox, 0, 25, 5, FALSE, FALSE, 0 );
 
    abutton1 = dw_bitmapbutton_new_from_file( "Should be under Top button", 0, "junk" );
    dw_box_pack_start( filetoolbarbox, abutton1, 25, 25, FALSE, FALSE, 0);
-   dw_signal_connect( abutton1, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(redraw_button_box_callback), NULL );
+   dw_signal_connect( abutton1, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(change_color_yellow_callback), NULL );
    dw_box_pack_start( filetoolbarbox, 0, 25, 5, FALSE, FALSE, 0 );
 
    abutton1 = dw_bitmapbutton_new_from_file( "Should be under Top button", 0, "junk" );
@@ -1167,7 +1188,7 @@
    dw_html_url(html, "http://www.rexx.org");
 
    dw_signal_connect(mainwindow, DW_SIGNAL_DELETE, DW_SIGNAL_FUNC(exit_callback), (void *)mainwindow);
-   timerid = dw_timer_connect(1000, DW_SIGNAL_FUNC(timer_callback), 0);
+   timerid = dw_timer_connect(2000, DW_SIGNAL_FUNC(timer_callback), 0);
    dw_window_set_size(mainwindow, 640, 520);
    dw_window_show(mainwindow);
 
--- a/dww-mingw.def	Tue Jan 06 11:00:15 2009 +0000
+++ b/dww-mingw.def	Fri Apr 10 10:25:26 2009 +0000
@@ -59,10 +59,12 @@
   dw_window_redraw                       @79
 
   dw_bitmap_new                          @80
+  dw_window_set_bitmap_from_data         @81
 
   dw_button_new                          @90
   dw_bitmapbutton_new                    @91
   dw_bitmapbutton_new_from_file          @92
+  dw_bitmapbutton_new_from_data          @93
 
   dw_text_new                            @100
   dw_status_text_new                     @101
@@ -117,6 +119,7 @@
   dw_icon_load                           @210
   dw_icon_free                           @211
   dw_icon_load_from_file                 @212
+  dw_icon_load_from_data                 @213
 
   dw_container_new                       @220
   dw_container_setup                     @221
@@ -146,9 +149,10 @@
   dw_screen_width                        @250
   dw_screen_height                       @251
 
-  dw_color_depth_get                         @260
+  dw_color_depth_get                     @260
   dw_color_foreground_set                @261
   dw_color_background_set                @262
+  dw_color_choose                        @263
 
   dw_notebook_new                        @270
   dw_notebook_page_new                   @271
@@ -190,12 +194,15 @@
   dw_draw_line                           @332
   dw_draw_rect                           @333
   dw_draw_text                           @334
+  dw_draw_polygon                        @335
 
   dw_pixmap_bitblt                       @340
   dw_pixmap_new                          @341
   dw_pixmap_grab                         @342
   dw_pixmap_destroy                      @343
   dw_pixmap_new_from_file                @344
+  dw_pixmap_new_from_data                @345
+  dw_pixmap_set_transparent_color        @346
 
   dw_dialog_new                          @350
   dw_dialog_dismiss                      @351
@@ -258,3 +265,17 @@
   dw_named_event_post                    @463
   dw_named_event_wait                    @464
   dw_named_event_close                   @465
+
+  dw_html_new                            @470
+  dw_html_action                         @471
+  dw_html_raw                            @472
+  dw_html_url                            @473
+
+  dw_calendar_new                        @480
+  dw_calendar_set_date                   @481
+  dw_calendar_get_date                   @482
+
+
+  dw_clipboard_get_text                  @490
+  dw_clipboard_set_text                  @491
+
--- a/dww.def	Tue Jan 06 11:00:15 2009 +0000
+++ b/dww.def	Fri Apr 10 10:25:26 2009 +0000
@@ -194,6 +194,7 @@
   dw_draw_line                           @332
   dw_draw_rect                           @333
   dw_draw_text                           @334
+  dw_draw_polygon                        @335
 
   dw_pixmap_bitblt                       @340
   dw_pixmap_new                          @341
@@ -201,6 +202,7 @@
   dw_pixmap_destroy                      @343
   dw_pixmap_new_from_file                @344
   dw_pixmap_new_from_data                @345
+  dw_pixmap_set_transparent_color        @346
 
   dw_dialog_new                          @350
   dw_dialog_dismiss                      @351
--- a/makefile.vc	Tue Jan 06 11:00:15 2009 +0000
+++ b/makefile.vc	Fri Apr 10 10:25:26 2009 +0000
@@ -10,13 +10,21 @@
 FXLIBDIR=.\lib
 FXDLLDIR=.\dll
 
+!if "$(DEBUG)" == "Y"
+CFLAGS_DEBUG = -Z7 -Od # was -Zi
+LINK_DEBUG = -debug:full
+!else
+CFLAGS_DEBUG = -Ox
+LINK_DEBUG = -release
+!endif
+
 CC = cl
 CFLAGS = -c -G5 -GD -Zp1 -DWIN32 -D__WIN32__ -DMSVC -DBUILD_DLL -I$(SRCDIR)\platform -I$(SRCDIR)
-CFLAGS_DEBUG = -Zi
-CFLAGS_COMPILE = -MTd
+#CFLAGS_COMPILE = -MTd
+CFLAGS_COMPILE = -MD
 LIBS = wsock32.lib kernel32.lib user32.lib comctl32.lib gdi32.lib advapi32.lib shell32.lib comdlg32.lib ole32.lib oleaut32.lib
 RES =
-LINKFLAGS = -machine:i386 -debug:full
+LINKFLAGS = -machine:i386 $(LINK_DEBUG)
 DLLLINKFLAGS = -dll
 LINK = link
 DEFFILE = $(SRCDIR)\dww.def
--- a/win/dw.c	Tue Jan 06 11:00:15 2009 +0000
+++ b/win/dw.c	Fri Apr 10 10:25:26 2009 +0000
@@ -67,6 +67,7 @@
 HPEN _hPen[THREAD_LIMIT];
 HBRUSH _hBrush[THREAD_LIMIT];
 char *_clipboard_contents[THREAD_LIMIT];
+int _PointerOnWnd[THREAD_LIMIT];
 
 BYTE _red[] = {   0x00, 0xbb, 0x00, 0xaa, 0x00, 0xbb, 0x00, 0xaa, 0x77,
            0xff, 0x00, 0xee, 0x00, 0xff, 0x00, 0xff, 0xaa, 0x00 };
@@ -77,6 +78,7 @@
 
 HBRUSH _colors[18];
 
+static int screenx, screeny;
 
 LRESULT CALLBACK _browserWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 void _resize_notebook_page(HWND handle, int pageid);
@@ -261,6 +263,107 @@
    return isnt;
 }
 
+void DrawTransparentBitmap(HDC hdc, HDC hdcSrc, HBITMAP hBitmap, int xStart, int yStart, COLORREF cTransparentColor)
+{
+   BITMAP bm;
+   COLORREF cColor;
+   HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
+   HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
+   HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
+   POINT ptSize;
+
+#if 0
+   hdcTemp = CreateCompatibleDC(hdc);
+   SelectObject(hdcTemp, hBitmap); // Select the bitmap
+#else
+   hdcTemp = hdcSrc;
+#endif
+
+   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
+   ptSize.x = bm.bmWidth; // Get width of bitmap
+   ptSize.y = bm.bmHeight; // Get height of bitmap
+   DPtoLP(hdcTemp, &ptSize, 1); // Convert from device
+
+   // to logical points
+
+   // Create some DCs to hold temporary data.
+   hdcBack = CreateCompatibleDC(hdc);
+   hdcObject = CreateCompatibleDC(hdc);
+   hdcMem = CreateCompatibleDC(hdc);
+   hdcSave = CreateCompatibleDC(hdc);
+
+   // Create a bitmap for each DC. DCs are required for a number of
+   // GDI functions.
+
+   // Monochrome DC
+   bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
+
+   // Monochrome DC
+   bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
+
+   bmAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
+   bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
+
+   // Each DC must select a bitmap object to store pixel data.
+   bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack);
+   bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
+   bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem);
+   bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave);
+
+   // Set proper mapping mode.
+   SetMapMode(hdcTemp, GetMapMode(hdc));
+
+   // Save the bitmap sent here, because it will be overwritten.
+   BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
+
+   // Set the background color of the source DC to the color.
+   // contained in the parts of the bitmap that should be transparent
+   cColor = SetBkColor(hdcTemp, cTransparentColor);
+
+   // Create the object mask for the bitmap by performing a BitBlt
+   // from the source bitmap to a monochrome bitmap.
+   BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
+
+   // Set the background color of the source DC back to the original
+   // color.
+   SetBkColor(hdcTemp, cColor);
+
+   // Create the inverse of the object mask.
+   BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY);
+
+   // Copy the background of the main DC to the destination.
+   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart, SRCCOPY);
+
+   // Mask out the places where the bitmap will be placed.
+   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
+
+   // Mask out the transparent colored pixels on the bitmap.
+   BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
+
+   // XOR the bitmap with the background on the destination DC.
+   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
+
+   // Copy the destination to the screen.
+   BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0,
+   SRCCOPY);
+
+   // Place the original bitmap back into the bitmap sent here.
+   BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
+
+   // Delete the memory bitmaps.
+   DeleteObject(SelectObject(hdcBack, bmBackOld));
+   DeleteObject(SelectObject(hdcObject, bmObjectOld));
+   DeleteObject(SelectObject(hdcMem, bmMemOld));
+   DeleteObject(SelectObject(hdcSave, bmSaveOld));
+
+   // Delete the memory DCs.
+   DeleteDC(hdcMem);
+   DeleteDC(hdcBack);
+   DeleteDC(hdcObject);
+   DeleteDC(hdcSave);
+   DeleteDC(hdcTemp);
+}
+
 DWORD GetDllVersion(LPCTSTR lpszDllName)
 {
 
@@ -1303,8 +1406,10 @@
                   Box *boxinfo = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA);
 
                   if(boxinfo && boxinfo->grouphwnd)
+                  {
                      MoveWindow(boxinfo->grouphwnd, 0, 0,
                               width + vectorx, height + vectory, FALSE);
+                  }
 
                }
             }
@@ -1513,7 +1618,6 @@
                case WM_SIZE:
                   {
                      int (*sizefunc)(HWND, int, int, void *) = tmp->signalfunction;
-
                      if(hWnd == tmp->window)
                      {
                         result = sizefunc(tmp->window, LOWORD(mp2), HIWORD(mp2), tmp->data);
@@ -1653,7 +1757,7 @@
                      DWExpose exp;
                      int (*exposefunc)(HWND, DWExpose *, void *) = tmp->signalfunction;
 
-                     if(hWnd == tmp->window)
+                     if ( hWnd == tmp->window )
                      {
                         BeginPaint(hWnd, &ps);
                         exp.x = ps.rcPaint.left;
@@ -1833,8 +1937,8 @@
                            result = clickfunc(tmp->window, tmp->data);
                            tmp = NULL;
                         }
-                     } /* Make sure it's the right window, and the right ID */
-                     else if (tmp->window < (HWND)65536 && command == tmp->window)
+                     } /* this fires for checkable menu items */
+                     else if ( tmp->window < (HWND)65536 && command == tmp->window && tmp->message != WM_TIMER )
                      {
                         _dw_toggle_checkable_menu_item( popup ? popup : tmp->window, (int)tmp->data );
                         result = clickfunc(popup ? popup : tmp->window, tmp->data);
@@ -1846,7 +1950,7 @@
                case WM_VSCROLL:
                   {
                      char tmpbuf[100];
-                           HWND handle = (HWND)mp2;
+                     HWND handle = (HWND)mp2;
                      int (*valuechangefunc)(HWND, int, void *) = tmp->signalfunction;
 
                      GetClassName(handle, tmpbuf, 99);
@@ -1983,6 +2087,7 @@
    case WM_VSCROLL:
       {
          HWND handle = (HWND)mp2;
+         char tmpbuf[100];
 
          if(dw_window_get_data(handle, "_dw_scrollbar"))
          {
@@ -1991,7 +2096,11 @@
             if(value > -1)
                dw_scrollbar_set_pos(handle, value);
          }
-      }
+         GetClassName( hWnd, tmpbuf, 99 );
+         if ( strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1 ) == 0 )
+         {
+            int value = _HandleScroller(hWnd, (int)HIWORD(mp1), (int)LOWORD(mp1));
+      }  }
       break;
    case WM_GETMINMAXINFO:
       {
@@ -2096,7 +2205,9 @@
    if(result != -1)
       return result;
    else
+   {
       return DefWindowProc(hWnd, msg, mp1, mp2);
+   }
 }
 
 VOID CALLBACK _TimerProc(HWND hwnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
@@ -2204,6 +2315,12 @@
 
 BOOL CALLBACK _rendwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
 {
+   RECT wndRect;
+   POINTS points;
+   POINT point;
+   int threadid = dw_thread_id();
+
+
    switch( msg )
    {
    case WM_LBUTTONDOWN:
@@ -2212,10 +2329,41 @@
       SetFocus(hWnd);
       _wndproc(hWnd, msg, mp1, mp2);
       break;
+   case WM_MOUSEMOVE:
+      if ( threadid < 0 || threadid >= THREAD_LIMIT )
+         threadid = 0;
+      /*
+       * Set the mouse capture and focus on the renderbox
+       * when the mouse moves into the window.
+       */
+      points = MAKEPOINTS(mp2); /* get the mouse point */
+      point.x = points.x;
+      point.y = points.y;
+      SetCapture( hWnd ); /*  Capture the mouse input */
+
+      GetWindowRect( hWnd, &wndRect );
+      ClientToScreen( hWnd, &point );
+
+      if ( PtInRect( &wndRect, point ) )
+      {  // Test if the pointer is on the window
+
+         if ( _PointerOnWnd[threadid] == 0 )
+         {
+            SetFocus(hWnd);
+            _PointerOnWnd[threadid] = 1;
+         }
+      }
+      else
+      {
+         ReleaseCapture();
+         _PointerOnWnd[threadid] = 0;
+      }
+      /* call our standard Windows procedure */
+      _wndproc(hWnd, msg, mp1, mp2);
+      break;
    case WM_LBUTTONUP:
    case WM_MBUTTONUP:
    case WM_RBUTTONUP:
-   case WM_MOUSEMOVE:
    case WM_PAINT:
    case WM_SIZE:
    case WM_COMMAND:
@@ -2989,13 +3137,30 @@
 {
    BubbleButton *bubble;
    static int bMouseOver = 0;
+   static BubbleButton *this_bubble = NULL;
    POINT point;
    RECT rect;
    WNDPROC pOldProc;
 
    bubble = (BubbleButton *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
-
-   if(!bubble)
+   if ( bubble != this_bubble )
+   {
+      /*
+       * If we missed the release capture, then if the bubble details
+       * from this window are different from the last we must be in a
+       * different button, so delete the last bubble text
+       */
+      bMouseOver = 0;
+      this_bubble = bubble;
+      if ( hwndBubble )
+      {
+         _free_window_memory(hwndBubble, 0);
+         DestroyWindow(hwndBubble);
+         hwndBubble = 0;
+      }
+   }
+
+   if ( !bubble )
       return DefWindowProc(hwnd, msg, mp1, mp2);
 
    /* We must save a pointer to the old
@@ -3022,6 +3187,16 @@
    case WM_LBUTTONUP:
       {
          SignalHandler *tmp = Root;
+         /*
+          * If we have bubbletext displaying when we
+          * release the mouse, get rid of the bubbletext window
+          */
+         if ( hwndBubble )
+         {
+            _free_window_memory(hwndBubble, 0);
+            DestroyWindow(hwndBubble);
+            hwndBubble = 0;
+         }
 
          /* Find any callbacks for this function */
          while(tmp)
@@ -3095,13 +3270,13 @@
       GetCursorPos(&point);
       GetWindowRect(hwnd, &rect);
 
-      if(PtInRect(&rect, point))
-      {
-         if(hwnd != GetCapture())
+      if ( PtInRect(&rect, point) )
+      {
+         if ( hwnd != GetCapture() )
          {
             SetCapture(hwnd);
          }
-         if(!bMouseOver)
+         if ( !bMouseOver )
          {
             bMouseOver = 1;
             if(!*bubble->bubbletext)
@@ -3190,7 +3365,7 @@
        * Either because we intentionally lost it or another window
        * stole it
        */
-      if(bMouseOver && hwndBubble)
+      if ( bMouseOver && hwndBubble )
       {
          bMouseOver = 0;
          _free_window_memory(hwndBubble, 0);
@@ -3200,7 +3375,7 @@
       break;
    }
 
-   if(!pOldProc)
+   if ( !pOldProc )
       return DefWindowProc(hwnd, msg, mp1, mp2);
    return CallWindowProc(pOldProc, hwnd, msg, mp1, mp2);
 }
@@ -3268,6 +3443,11 @@
          *hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
          windowtype = BS_BITMAP;
       }
+      else if ( stricmp( file + len - 4, ".png" ) == 0 )
+      {
+         *hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
+         windowtype = BS_BITMAP;
+      }
       free(file);
    }
    else
@@ -3405,6 +3585,7 @@
       _hPen[z] = CreatePen(PS_SOLID, 1, _foreground[z]);
       _hBrush[z] = CreateSolidBrush(_foreground[z]);
       _clipboard_contents[z] = NULL;
+      _PointerOnWnd[z] = 0;
    }
 
    if ( !IS_WINNTOR95 )
@@ -3429,6 +3610,13 @@
    {
       dbgfp = fopen( fname, "w" );
    }
+   /*
+    * Get screen size. Used to make calls to dw_screen_width()
+    * and dw_screen-height() quicker, but to alos limit the
+    * default size of windows.
+    */
+   screenx = GetSystemMetrics(SM_CXSCREEN);
+   screeny = GetSystemMetrics(SM_CYSCREEN);
    return 0;
 }
 
@@ -3865,9 +4053,11 @@
 int API dw_window_set_color(HWND handle, ULONG fore, ULONG back)
 {
    ColorInfo *cinfo;
+   Box *newbox;
    char tmpbuf[100];
 
    cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+   newbox = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA);
 
    GetClassName(handle, tmpbuf, 99);
 
@@ -4043,6 +4233,40 @@
 }
 
 /*
+ * INCOMPLETE
+ * Create a new scroll Box to be packed.
+ * Parameters:
+ *       type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
+ *       pad: Number of pixels to pad around the box.
+ */
+HWND API dw_scrollbox_new(int type, int pad)
+{
+   Box *newbox = calloc(sizeof(Box), 1);
+   HWND hwndframe;
+
+   newbox->pad = pad;
+   newbox->type = type;
+   newbox->count = 0;
+   newbox->grouphwnd = (HWND)NULL;
+   newbox->cinfo.fore = newbox->cinfo.back = -1;
+
+   hwndframe = CreateWindow(FRAMECLASSNAME,
+                      "",
+                      WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
+                      0,0,2000,1000,
+                      DW_HWND_OBJECT,
+                      NULL,
+                      DWInstance,
+                      NULL);
+
+   newbox->cinfo.pOldProc = SubclassWindow(hwndframe, _colorwndproc);
+   newbox->cinfo.fore = newbox->cinfo.back = -1;
+
+   SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox);
+   return hwndframe;
+}
+
+/*
  * Create a new Group Box to be packed.
  * Parameters:
  *       type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
@@ -4457,9 +4681,8 @@
    dw_window_set_data( DW_HWND_OBJECT, buffer2, (void *)disabled );
 }
 
-#if 0
-/*
- * TBD
+/*
+ * INCOMPLETE
  * Deletes the menu item specified
  * Parameters:
  *       menu: The handle to the  menu in which the item was appended.
@@ -4469,13 +4692,17 @@
 {
    HMENU mymenu = (HMENU)menux;
 
-   if(IsWindow(menux) && !IsMenu(mymenu))
+   if ( IsWindow(menux) && !IsMenu(mymenu) )
       mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu");
 
-   DeleteMenu(mymenu, id, MF_BYCOMMAND);
+   if ( DeleteMenu(mymenu, id, MF_BYCOMMAND) == 0 )
+   {
+      char lasterror[257];
+      FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), lasterror, 256, NULL);
+      fprintf(stderr, "Error deleting menu: %s", lasterror);
+   }
    DrawMenuBar(menux);
 }
-#endif
 
 /*
  * Pops up a context menu at given x and y coordinates.
@@ -4855,15 +5082,11 @@
 
    if(icon)
    {
-      SendMessage(tmp, BM_SETIMAGE,
-               (WPARAM) IMAGE_ICON,
-               (LPARAM) icon);
+      SendMessage(tmp, BM_SETIMAGE, (WPARAM) IMAGE_ICON, (LPARAM) icon);
    }
    else if(hbitmap)
    {
-      SendMessage(tmp, BM_SETIMAGE,
-               (WPARAM) IMAGE_BITMAP,
-               (LPARAM) hbitmap);
+      SendMessage(tmp, BM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) hbitmap);
    }
    return tmp;
 }
@@ -4892,8 +5115,6 @@
 
    tmp = CreateWindow( BUTTONCLASSNAME,
                        "",
-//                     label_text,
-//                     WS_CHILD | BS_OWNERDRAW | WS_CLIPCHILDREN | WS_VISIBLE,
                        windowtype | WS_CHILD | BS_PUSHBUTTON | WS_CLIPCHILDREN | WS_VISIBLE,
                        0,0,2000,1000,
                        DW_HWND_OBJECT,
@@ -4987,15 +5208,11 @@
 
    if ( icon )
    {
-      SendMessage( tmp, BM_SETIMAGE,
-                   (WPARAM) IMAGE_ICON,
-                   (LPARAM) icon);
+      SendMessage( tmp, BM_SETIMAGE, (WPARAM) IMAGE_ICON, (LPARAM) icon);
    }
    else if( hbitmap )
    {
-      SendMessage( tmp, BM_SETIMAGE,
-                   (WPARAM) IMAGE_BITMAP,
-                   (LPARAM) hbitmap);
+      SendMessage( tmp, BM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) hbitmap);
    }
    return tmp;
 }
@@ -5367,6 +5584,7 @@
  */
 void API dw_window_set_text(HWND handle, char *text)
 {
+   Box *thisbox;
    char tmpbuf[100];
 
    GetClassName(handle, tmpbuf, 99);
@@ -5374,8 +5592,15 @@
    SetWindowText(handle, text);
 
    /* Combobox */
-   if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+   if ( strnicmp( tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1) == 0 )
       SendMessage(handle, CB_SETEDITSEL, 0, MAKELPARAM(-1, 0));
+   else if ( strnicmp( tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1) == 0 )
+   {
+      /* groupbox */
+      thisbox = (Box *)GetWindowLongPtr( handle, GWLP_USERDATA );
+      if ( thisbox && thisbox->grouphwnd != (HWND)NULL )
+         SetWindowText( thisbox->grouphwnd, text );
+   }
 }
 
 /*
@@ -5567,6 +5792,10 @@
    if ( width == 0 ) width = usedx;
    if ( height == 0 ) height = usedy;
    SetWindowPos(handle, (HWND)NULL, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOMOVE);
+#if 0
+   /* force a configure event */
+   SendMessage( handle, WM_SIZE, 0, MAKELPARAM(usedx, usedy) );
+#endif
 }
 
 /*
@@ -5574,7 +5803,7 @@
  */
 int API dw_screen_width(void)
 {
-   return GetSystemMetrics(SM_CXSCREEN);
+   return screenx;
 }
 
 /*
@@ -5582,7 +5811,7 @@
  */
 int API dw_screen_height(void)
 {
-   return GetSystemMetrics(SM_CYSCREEN);
+   return screeny;
 }
 
 /* This should return the current color depth */
@@ -5606,7 +5835,7 @@
  *          x: X location from the bottom left.
  *          y: Y location from the bottom left.
  */
-void API dw_window_set_pos(HWND handle, ULONG x, ULONG y)
+void API dw_window_set_pos(HWND handle, long x, long y)
 {
    SetWindowPos(handle, (HWND)NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
 }
@@ -5620,7 +5849,7 @@
  *          width: Width of the widget.
  *          height: Height of the widget.
  */
-void API dw_window_set_pos_size(HWND handle, ULONG x, ULONG y, ULONG width, ULONG height)
+void API dw_window_set_pos_size(HWND handle, long x, long y, ULONG width, ULONG height)
 {
    int usedx = 0, usedy = 0, depth = 0, usedpadx = 0, usedpady = 0;
    Box *thisbox;
@@ -5635,7 +5864,13 @@
       _resize_box(thisbox, &depth, 0, 0, &usedx, &usedy, 1, &usedpadx, &usedpady);
       _resize_box(thisbox, &depth, usedx, usedy, &usedx, &usedy, 2, &usedpadx, &usedpady);
    }
+   if ( width == 0 ) width = usedx;
+   if ( height == 0 ) height = usedy;
    SetWindowPos(handle, (HWND)NULL, x, y, width, height, SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE);
+#if 0
+   /* force a configure event */
+   SendMessage( handle, WM_SIZE, 0, MAKELPARAM(width, height) );
+#endif
 }
 
 /*
@@ -5647,7 +5882,7 @@
  *          width: Width of the widget.
  *          height: Height of the widget.
  */
-void API dw_window_get_pos_size(HWND handle, ULONG *x, ULONG *y, ULONG *width, ULONG *height)
+void API dw_window_get_pos_size(HWND handle, long *x, long *y, ULONG *width, ULONG *height)
 {
    WINDOWPLACEMENT wp;
 
@@ -5665,7 +5900,7 @@
       if(height)
          *height=dw_screen_height();
    }
-else
+   else
    {
       if(x)
          *x = wp.rcNormalPosition.left;
@@ -7750,7 +7985,7 @@
    HWND tmp = CreateWindow(ObjectClassName,
                      "",
                      WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN,
-                     0,0,2000,1000,
+                     0,0,screenx,screeny,
                      DW_HWND_OBJECT,
                      (HMENU)id,
                      DWInstance,
@@ -7761,8 +7996,7 @@
    newbox->grouphwnd = (HWND)NULL;
    newbox->cinfo.pOldProc = SubclassWindow(tmp, _rendwndproc);
    newbox->cinfo.fore = newbox->cinfo.back = -1;
-
-   SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)newbox);
+   SetWindowLongPtr( tmp, GWLP_USERDATA, (LONG_PTR)newbox );
    return tmp;
 }
 
@@ -7901,6 +8135,73 @@
       ReleaseDC(handle, hdcPaint);
 }
 
+/* Draw a closed polygon on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       fill: if true filled
+ *       number of points
+ *       x[]: X coordinates.
+ *       y[]: Y coordinates.
+ */
+void API dw_draw_polygon(HWND handle, HPIXMAP pixmap, int fill, int npoints, int *x, int *y)
+{
+   HDC hdcPaint;
+   HBRUSH oldBrush;
+   HPEN oldPen;
+   POINT *points;
+   int i;
+   int threadid = dw_thread_id();
+
+   if(threadid < 0 || threadid >= THREAD_LIMIT)
+      threadid = 0;
+
+   if ( handle )
+      hdcPaint = GetDC( handle );
+   else if ( pixmap )
+      hdcPaint = pixmap->hdc;
+   else
+      return;
+   if ( npoints )
+   {
+      /*
+       * Allocate enough space for the number of points supplied plus 1.
+       * Under windows, unless the first and last points are the same
+       * the polygon won't be closed
+       */
+      points = (POINT *)malloc( (npoints+1) * sizeof(POINT) );
+      /*
+       * should check for NULL pointer return!
+       */
+      for ( i = 0 ; i < npoints ; i++ )
+      {
+         points[i].x = x[i];
+         points[i].y = y[i];
+      }
+      if ( !( points[0].x == points[npoints-1].x
+      &&   points[0].y == points[npoints-1].y ) )
+      {
+         /* set the last point to be the same as the first point... */
+         points[npoints].x = points[0].x;
+         points[npoints].y = points[0].y;
+         /* ... and increment the number of points */
+         npoints++;
+      }
+   }
+
+   oldBrush = SelectObject( hdcPaint, _hBrush[threadid] );
+   oldPen = SelectObject( hdcPaint, _hPen[threadid] );
+   if ( fill )
+      Polygon( hdcPaint, points, npoints );
+   else
+      Polyline( hdcPaint, points, npoints );
+   SelectObject( hdcPaint, oldBrush );
+   SelectObject( hdcPaint, oldPen );
+   if ( !pixmap )
+      ReleaseDC( handle, hdcPaint );
+   free(points);
+}
+
 /* Draw a rectangle on a window (preferably a render window).
  * Parameters:
  *       handle: Handle to the window.
@@ -8065,6 +8366,8 @@
 {
    HPIXMAP pixmap;
    HDC hdc;
+   COLORREF bkcolor;
+   ULONG cx, cy;
 
    if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
       return NULL;
@@ -8076,11 +8379,18 @@
    pixmap->handle = handle;
    pixmap->hbm = CreateCompatibleBitmap(hdc, width, height);
    pixmap->hdc = CreateCompatibleDC(hdc);
+   pixmap->transcolor = DW_RGB_TRANSPARENT;
 
    SelectObject(pixmap->hdc, pixmap->hbm);
 
    ReleaseDC(handle, hdc);
 
+#if 0
+   /* force a CONFIGURE event on the underlying renderbox */
+   dw_window_get_pos_size( handle, NULL, NULL, &cx, &cy );
+   SendMessage( handle, WM_SIZE, 0, MAKELPARAM(cx, cy) );
+#endif
+
    return pixmap;
 }
 
@@ -8099,6 +8409,7 @@
    HPIXMAP pixmap;
    BITMAP bm;
    HDC hdc;
+   ULONG cx, cy;
    char *file = malloc(strlen(filename) + 5);
 
    if (!file || !(pixmap = calloc(1,sizeof(struct _hpixmap))))
@@ -8128,7 +8439,7 @@
    pixmap->handle = handle;
    pixmap->hbm = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
 
-   if(!pixmap->hbm)
+   if ( !pixmap->hbm )
    {
       free(file);
       free(pixmap);
@@ -8136,18 +8447,19 @@
       return NULL;
    }
 
-   pixmap->hdc = CreateCompatibleDC(hdc);
-
-    GetObject(pixmap->hbm, sizeof(bm), &bm);
-
+   pixmap->hdc = CreateCompatibleDC( hdc );
+   GetObject( pixmap->hbm, sizeof(bm), &bm );
    pixmap->width = bm.bmWidth; pixmap->height = bm.bmHeight;
-
-   SelectObject(pixmap->hdc, pixmap->hbm);
-
-   ReleaseDC(handle, hdc);
-
-   free(file);
-
+   SelectObject( pixmap->hdc, pixmap->hbm );
+   ReleaseDC( handle, hdc );
+   free( file );
+   pixmap->transcolor = DW_RGB_TRANSPARENT;
+
+#if 0
+   /* force a CONFIGURE event on the underlying renderbox */
+   dw_window_get_pos_size( handle, NULL, NULL, &cx, &cy );
+   SendMessage( handle, WM_SIZE, 0, MAKELPARAM(cx, cy) );
+#endif
    return pixmap;
 }
 
@@ -8168,6 +8480,7 @@
    HDC hdc;
    char *file;
    FILE *fp;
+   ULONG cx, cy;
 
    if ( !(pixmap = calloc(1,sizeof(struct _hpixmap))) )
    {
@@ -8213,11 +8526,29 @@
    SelectObject( pixmap->hdc, pixmap->hbm );
 
    ReleaseDC( handle, hdc );
+   pixmap->transcolor = DW_RGB_TRANSPARENT;
+
+#if 0
+   /* force a CONFIGURE event on the underlying renderbox */
+   dw_window_get_pos_size( handle, NULL, NULL, &cx, &cy );
+   SendMessage( handle, WM_SIZE, 0, MAKELPARAM(cx, cy) );
+#endif
 
    return pixmap;
 }
 
 /*
+ * Creates a bitmap mask for rendering bitmaps with transparent backgrounds
+ */
+void API dw_pixmap_set_transparent_color( HPIXMAP pixmap, ULONG color )
+{
+   if ( pixmap )
+   {
+      pixmap->transcolor = _internal_color(color);
+   }
+}
+
+/*
  * Creates a pixmap from internal resource graphic specified by id.
  * Parameters:
  *       handle: Window handle the pixmap is associated with.
@@ -8261,9 +8592,9 @@
 {
    if(pixmap)
    {
-      DeleteDC(pixmap->hdc);
-      DeleteObject(pixmap->hbm);
-      free(pixmap);
+      DeleteDC( pixmap->hdc );
+      DeleteObject( pixmap->hbm );
+      free( pixmap );
    }
 }
 
@@ -8285,27 +8616,33 @@
 {
    HDC hdcdest;
    HDC hdcsrc;
-
-   if(dest)
-      hdcdest = GetDC(dest);
-   else if(destp)
+   HDC hdcMem;
+
+   if ( dest )
+      hdcdest = GetDC( dest );
+   else if ( destp )
       hdcdest = destp->hdc;
    else
       return;
 
-   if(src)
-      hdcsrc = GetDC(src);
-   else if(srcp)
+   if ( src )
+      hdcsrc = GetDC( src );
+   else if ( srcp )
       hdcsrc = srcp->hdc;
    else
       return;
-
-   BitBlt(hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, SRCCOPY);
-
-   if(!destp)
-      ReleaseDC(dest, hdcdest);
-   if(!srcp)
-      ReleaseDC(src, hdcsrc);
+   if ( srcp && srcp->transcolor != DW_RGB_TRANSPARENT )
+   {
+      DrawTransparentBitmap( hdcdest, srcp->hdc, srcp->hbm, xdest, ydest, RGB( DW_RED_VALUE(srcp->transcolor), DW_GREEN_VALUE(srcp->transcolor), DW_BLUE_VALUE(srcp->transcolor)) );
+   }
+   else
+   {
+      BitBlt( hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, SRCCOPY );
+   }
+   if ( !destp )
+      ReleaseDC( dest, hdcdest );
+   if ( !srcp )
+      ReleaseDC( src, hdcsrc );
 }
 
 /* Run Beep() in a separate thread so it doesn't block */