Problems with wizard code in COMCTL32

Filip Navara xnavara at volny.cz
Wed Jul 21 13:52:34 CDT 2004


Hi,

I took a quick look at the property sheet code in COMCTL32 in order to 
get the Mozilla Firefox setup working. The attached patch fixes some of 
the bugs, but the code is too messy for me to understand and fix the 
other problems:

- Line ~1532. When PSH_USEHBMWATERMARK or PSH_USEHBMHEADER is set, the 
property sheet header is modified and the watermark/header bitmap is 
loaded using CreateMappedBitmap and injected into the 
hbmWatermark/hbmHeader field of the global property sheet info 
structure. This is done for every page in the property sheet. Since the 
names and bitmaps are stored as union at the same place in memory, on 
the second page the bitmap is already loaded and the original name is 
already lost, but the PSH_USEHBM* flag is still set and so the code 
tries to load the bitmap again passing the bitmap handle instead of the 
resource ID. I think the code for loading the watermark and header 
bitmaps should be moved to some other initialization routine, because 
AFAIK these bitmaps are identical for the whole wizard and not different 
on per page basis.

- The watermark bitmap is displayed under the "dialog" with the controls 
on the property sheet. The "dialog" itself isn't transparent and so most 
of the watermark bitmap isn't visible. I thought that setting the window 
class background color of the "dialog" with controls would solve that, 
but it seems that the native version of COMCTL32 (from Windows XP) 
subclasses it.

- Caption of the wizard window is never set.

If anyone wants to look at these problems it would be great.

Regards,
Filip
-------------- next part --------------
Changelog:
- Properly calculate caption length when converting multi-byte string to
  wide character one.
- Wizard contents shouldn't be moved by the size of watermark bitmap.
- Fix PSH_WIZARD97_[NEW/OLD] checks.
- Blit the watermark even if PSH_USEHBMWATERMARK flag isn't set and blit only
  the part that fits into the dialog.
- Fix CreateMappedBitmap for palette-less bitmaps.

Index: comctl32/propsheet.c
===================================================================
--- comctl32/propsheet.c	(revision 1)
+++ comctl32/propsheet.c	(working copy)
@@ -173,7 +173,7 @@
 static BOOL PROPSHEET_RemovePage(HWND hwndDlg,
                                  int index,
                                  HPROPSHEETPAGE hpage);
-static void PROPSHEET_CleanUp();
+static void PROPSHEET_CleanUp(HWND hwndDlg);
 static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo);
 static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags);
 static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg, const PropSheetInfo* psInfo);
@@ -308,10 +308,9 @@
   {
      if (HIWORD(lppsh->pszCaption))
      {
-        int len = strlen(lppsh->pszCaption);
+        int len = MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, NULL, 0);
         psInfo->ppshheader.pszCaption = HeapAlloc( GetProcessHeap(), 0, (len+1)*sizeof (WCHAR) );
         MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, (LPWSTR) psInfo->ppshheader.pszCaption, len+1);
-        /* strcpy( (char *)psInfo->ppshheader.pszCaption, lppsh->pszCaption ); */
      }
   }
   psInfo->nPages = lppsh->nPages;
@@ -361,7 +360,7 @@
      psInfo->ppshheader.pszCaption = NULL;
   else
   {
-     if (!(lppsh->dwFlags & INTRNL_ANY_WIZARD) && HIWORD(lppsh->pszCaption))
+     if (HIWORD(lppsh->pszCaption))
      {
         int len = strlenW(lppsh->pszCaption);
         psInfo->ppshheader.pszCaption = HeapAlloc( GetProcessHeap(), 0, (len+1)*sizeof(WCHAR) );
@@ -1511,7 +1510,6 @@
   psInfo->proppage[index].hwndPage = hwndPage;
 
   if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) {     
-      int offsetx = 0;
       int offsety = 0;
       HWND hwndChild;
       RECT r;
@@ -1532,11 +1530,10 @@
 	    pageWidth, pageHeight, padding.x, padding.y);
 
       /* If there is a watermark, offset the dialog items */     
-      if ( (psInfo->ppshheader.dwFlags & (PSH_WATERMARK | PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
+      if ( (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) &&
+           (psInfo->ppshheader.dwFlags & PSH_WATERMARK) &&
 	   ((index == 0) || (index == psInfo->nPages - 1)) )
       {
-	  BITMAP bm;
-
 	  /* if PSH_USEHBMWATERMARK is not set, load the resource from pszbmWatermark 
 	     and put the HBITMAP in hbmWatermark. Thus all the rest of the code always 
 	     considers hbmWatermark as valid. */
@@ -1545,13 +1542,10 @@
 	      ((PropSheetInfo *)psInfo)->ppshheader.u4.hbmWatermark = 
 		  CreateMappedBitmap(ppshpage->hInstance, (INT)psInfo->ppshheader.u4.pszbmWatermark, 0, NULL, 0);
 	  }
-
-	  /* Compute the offset x */
-	  GetObjectA(psInfo->ppshheader.u4.hbmWatermark, sizeof(BITMAP), (LPVOID)&bm);
-	  offsetx = bm.bmWidth;
       }
 
-      if (psInfo->ppshheader.dwFlags & (PSH_HEADER | PSH_WIZARD97_NEW | PSH_WIZARD97_OLD))
+      if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD) &&
+          psInfo->ppshheader.dwFlags & PSH_HEADER)
       {
 	  /* Same behavior as for watermarks */
 	  if (!(psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER))
@@ -1567,21 +1561,10 @@
 	  offsety = (ppshpage->dwFlags & PSP_HIDEHEADER)?0:r.bottom + 1;
       }
 
-      hwndChild = GetWindow(hwndPage, GW_CHILD);
-      while((offsetx!=0) && (hwndChild)) {
-	  GetWindowRect(hwndChild, &r);
-	  MapWindowPoints(0, hwndPage, (LPPOINT)&r, 2);
-	  OffsetRect(&r, -offsetx, 0);
-	  SetWindowPos(hwndChild, 0, r.left, r.top, 
-		       0, 0, SWP_NOSIZE | SWP_NOZORDER);
-	  
-	  hwndChild = GetWindow(hwndChild, GW_HWNDNEXT);
-      }      
-
       SetWindowPos(hwndPage, HWND_TOP,
-		   rc.left + padding.x/2 + offsetx,
+		   rc.left + padding.x/2,
 		   rc.top + padding.y/2 + offsety,
-		   pageWidth - offsetx, pageHeight - offsety, 0);
+		   pageWidth, pageHeight - offsety, 0);
   }
   else {
       /*
@@ -2926,7 +2909,8 @@
 	hOldPal = SelectPalette(hdc, psInfo->ppshheader.hplWatermark, FALSE);
 
     if ( (!(ppshpage->dwFlags & PSP_HIDEHEADER)) &&
-	 (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_HEADER)) ) 
+	 (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
+	 (psInfo->ppshheader.dwFlags & PSH_HEADER) ) 
     {
 	RECT rzone;
 	HWND hwndLineHeader = GetDlgItem(hwnd, IDC_SUNKEN_LINEHEADER);
@@ -2982,35 +2966,33 @@
     }
 
     if ( ((psInfo->active_page == 0) || (psInfo->active_page == psInfo->nPages - 1)) &&
-	 (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WATERMARK)) ) 
+	 (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) &&
+	 (psInfo->ppshheader.dwFlags & PSH_WATERMARK) ) 
     {
-	if (psInfo->ppshheader.dwFlags & PSH_USEHBMWATERMARK ) 
-	{
-	    HWND hwndLine = GetDlgItem(hwnd, IDC_SUNKEN_LINE);	    
+	HWND hwndLine = GetDlgItem(hwnd, IDC_SUNKEN_LINE);	    
 
-	    GetClientRect(hwndLine, &r);
-	    MapWindowPoints(hwndLine, hwnd, (LPPOINT) &r, 2);
+	GetClientRect(hwndLine, &r);
+	MapWindowPoints(hwndLine, hwnd, (LPPOINT) &r, 2);
 
-	    GetObjectA(psInfo->ppshheader.u4.hbmWatermark, sizeof(BITMAP), (LPVOID)&bm);
-	    hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u4.hbmWatermark);
+	GetObjectA(psInfo->ppshheader.u4.hbmWatermark, sizeof(BITMAP), (LPVOID)&bm);
+	hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u4.hbmWatermark);
 
-	    BitBlt(hdc, 0, offsety, bm.bmWidth, bm.bmHeight, 
-		   hdcSrc, 0, 0, SRCCOPY);
+	BitBlt(hdc, 0, offsety, min(bm.bmWidth, r.right),
+	       min(bm.bmHeight, r.bottom), hdcSrc, 0, 0, SRCCOPY);
 
-	    /* If the bitmap is not big enough, fill the remaining area
-	       with the color of pixel (0,0) of bitmap - see MSDN */
-	    if (r.top > bm.bmHeight) {
-		r.bottom = r.top - 1;
-		r.top = bm.bmHeight;
-		r.left = 0;
-		r.right = bm.bmWidth;
-		hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0));
-		FillRect(hdc, &r, hbr);
-		DeleteObject(hbr);
-	    }
-
-	    SelectObject(hdcSrc, hbmp);	    
+	/* If the bitmap is not big enough, fill the remaining area
+	   with the color of pixel (0,0) of bitmap - see MSDN */
+	if (r.top > bm.bmHeight) {
+	    r.bottom = r.top - 1;
+	    r.top = bm.bmHeight;
+	    r.left = 0;
+	    r.right = bm.bmWidth;
+	    hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0));
+	    FillRect(hdc, &r, hbr);
+	    DeleteObject(hbr);
 	}
+
+	SelectObject(hdcSrc, hbmp);	    
     }
 
     if (psInfo->ppshheader.dwFlags & PSH_USEHPLWATERMARK) 
Index: comctl32/commctrl.c
===================================================================
--- comctl32/commctrl.c	(revision 1)
+++ comctl32/commctrl.c	(working copy)
@@ -862,7 +862,12 @@
     if (lpBitmap == NULL)
 	return 0;
 
-    nColorTableSize = (1 << lpBitmap->biBitCount);
+    if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
+        nColorTableSize = lpBitmap->biClrUsed;
+    else if (lpBitmap->biBitCount <= 8)	
+        nColorTableSize = (1 << lpBitmap->biBitCount);
+    else
+        nColorTableSize = 0;
     nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
     lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
     if (lpBitmapInfo == NULL)
@@ -899,7 +904,7 @@
 	HDC hdcDst = CreateCompatibleDC (hdcScreen);
 	HBITMAP hbmOld = SelectObject (hdcDst, hbm);
 	LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
-	lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
+	lpBits += nColorTableSize * sizeof(RGBQUAD);
 	StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
 		         lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
 		         SRCCOPY);


More information about the wine-devel mailing list