Migrated parent.c.

This commit is contained in:
Pietro Gagliardi 2016-04-22 18:11:20 -04:00
parent 9e90475e11
commit 027d1f15ee
2 changed files with 49 additions and 26 deletions

View File

@ -1,19 +1,19 @@
// 26 april 2015 // 26 april 2015
#include "uipriv_windows.h" #include "uipriv_windows.hpp"
// This contains code used by all uiControls that contain other controls. // This contains code used by all uiControls that contain other controls.
// It also contains the code to draw the background of a container.c container, as that is a variant of the WM_CTLCOLORxxx handler code. // It also contains the code to draw the background of a container.c container, as that is a variant of the WM_CTLCOLORxxx handler code.
static HBRUSH parentBrush = NULL; static HBRUSH parentBrush = NULL;
static HWND realParent(HWND hwnd) static HWND parentWithBackground(HWND hwnd)
{ {
HWND parent; HWND parent;
int class; int class;
parent = hwnd; parent = hwnd;
for (;;) { for (;;) {
parent = GetAncestor(parent, GA_PARENT); parent = parentOf(parent);
// skip groupboxes; they're (supposed to be) transparent // skip groupboxes; they're (supposed to be) transparent
// skip uiContainers; they don't draw anything // skip uiContainers; they don't draw anything
class = windowClassOf(parent, L"button", containerClass, NULL); class = windowClassOf(parent, L"button", containerClass, NULL);
@ -29,32 +29,37 @@ struct parentDraw {
HBITMAP prevbitmap; HBITMAP prevbitmap;
}; };
static void parentDraw(HDC dc, HWND parent, struct parentDraw *pd) static HRESULT parentDraw(HDC dc, HWND parent, struct parentDraw *pd)
{ {
RECT r; RECT r;
if (GetClientRect(parent, &r) == 0) if (GetClientRect(parent, &r) == 0)
logLastError("error getting parent's client rect in parentDraw()"); return logLastError(L"error getting parent's client rect");
pd->cdc = CreateCompatibleDC(dc); pd->cdc = CreateCompatibleDC(dc);
if (pd->cdc == NULL) if (pd->cdc == NULL)
logLastError("error creating compatible DC in parentDraw()"); return logLastError(L"error creating compatible DC");
pd->bitmap = CreateCompatibleBitmap(dc, r.right - r.left, r.bottom - r.top); pd->bitmap = CreateCompatibleBitmap(dc, r.right - r.left, r.bottom - r.top);
if (pd->bitmap == NULL) if (pd->bitmap == NULL)
logLastError("error creating compatible bitmap in parentDraw()"); return logLastError(L"error creating compatible bitmap");
pd->prevbitmap = SelectObject(pd->cdc, pd->bitmap); pd->prevbitmap = SelectObject(pd->cdc, pd->bitmap);
if (pd->prevbitmap == NULL) if (pd->prevbitmap == NULL)
logLastError("error selecting bitmap into compatible DC in parentDraw()"); return logLastError(L"error selecting bitmap into compatible DC");
SendMessageW(parent, WM_PRINTCLIENT, (WPARAM) (pd->cdc), PRF_CLIENT); SendMessageW(parent, WM_PRINTCLIENT, (WPARAM) (pd->cdc), PRF_CLIENT);
return S_OK;
} }
static void endParentDraw(struct parentDraw *pd) static void endParentDraw(struct parentDraw *pd)
{ {
// continue in case of any error
if (pd->prevbitmap != NULL)
if (SelectObject(pd->cdc, pd->prevbitmap) != pd->bitmap) if (SelectObject(pd->cdc, pd->prevbitmap) != pd->bitmap)
logLastError("error selecting previous bitmap back into compatible DC in endParentDraw()"); logLastError(L"error selecting previous bitmap back into compatible DC");
if (pd->bitmap != NULL)
if (DeleteObject(pd->bitmap) == 0) if (DeleteObject(pd->bitmap) == 0)
logLastError("error deleting compatible bitmap in endParentDraw()"); logLastError(L"error deleting compatible bitmap");
if (pd->cdc != NULL)
if (DeleteDC(pd->cdc) == 0) if (DeleteDC(pd->cdc) == 0)
logLastError("error deleting compatible DC in endParentDraw()"); logLastError(L"error deleting compatible DC");
} }
// see http://www.codeproject.com/Articles/5978/Correctly-drawn-themed-dialogs-in-WinXP // see http://www.codeproject.com/Articles/5978/Correctly-drawn-themed-dialogs-in-WinXP
@ -65,21 +70,29 @@ static HBRUSH getControlBackgroundBrush(HWND hwnd, HDC dc)
struct parentDraw pd; struct parentDraw pd;
HBRUSH brush; HBRUSH brush;
parent = realParent(hwnd); parent = parentWithBackground(hwnd);
parentDraw(dc, parent, &pd); hr = parentDraw(dc, parent, &pd);
if (hr != S_OK)
return NULL;
brush = CreatePatternBrush(pd.bitmap); brush = CreatePatternBrush(pd.bitmap);
if (brush == NULL) if (brush == NULL) {
logLastError("error creating pattern brush in getControlBackgroundBrush()"); logLastError(L"error creating pattern brush");
endParentDraw(&pd);
return NULL;
}
endParentDraw(&pd); endParentDraw(&pd);
// now figure out where the control is relative to the parent so we can align the brush properly // now figure out where the control is relative to the parent so we can align the brush properly
if (GetWindowRect(hwnd, &hwndScreenRect) == 0) // if anything fails, give up and return the brush as-is
logLastError("error getting control window rect in getControlBackgroundBrush()"); if (GetWindowRect(hwnd, &hwndScreenRect) == 0) {
logLastError(L"error getting control window rect");
return brush;
}
// this will be in screen coordinates; convert to parent coordinates // this will be in screen coordinates; convert to parent coordinates
mapWindowRect(NULL, parent, &hwndScreenRect); mapWindowRect(NULL, parent, &hwndScreenRect);
if (SetBrushOrgEx(dc, -hwndScreenRect.left, -hwndScreenRect.top, NULL) == 0) if (SetBrushOrgEx(dc, -hwndScreenRect.left, -hwndScreenRect.top, NULL) == 0)
logLastError("error setting brush origin in getControlBackgroundBrush()"); logLastError(L"error setting brush origin");
return brush; return brush;
} }
@ -89,20 +102,24 @@ void paintContainerBackground(HWND hwnd, HDC dc, RECT *paintRect)
HWND parent; HWND parent;
RECT paintRectParent; RECT paintRectParent;
struct parentDraw pd; struct parentDraw pd;
HRESULT hr;
parent = realParent(hwnd); parent = parentWithBackground(hwnd);
parentDraw(dc, parent, &pd); hr = parentDraw(dc, parent, &pd);
if (hr != S_OK) // we couldn't get it; draw nothing
return NULL;
paintRectParent = *paintRect; paintRectParent = *paintRect;
mapWindowRect(hwnd, parent, &paintRectParent); mapWindowRect(hwnd, parent, &paintRectParent);
if (BitBlt(dc, paintRect->left, paintRect->top, paintRect->right - paintRect->left, paintRect->bottom - paintRect->top, if (BitBlt(dc, paintRect->left, paintRect->top, paintRect->right - paintRect->left, paintRect->bottom - paintRect->top,
pd.cdc, paintRectParent.left, paintRectParent.top, pd.cdc, paintRectParent.left, paintRectParent.top,
SRCCOPY) == 0) SRCCOPY) == 0)
logLastError("error drawing parent background over uiContainer in paintContainerBackground()"); logLastError(L"error drawing parent background over uiContainer");
endParentDraw(&pd); endParentDraw(&pd);
} }
// TODO make this public if we want custom containers
// why have this to begin with? http://blogs.msdn.com/b/oldnewthing/archive/2010/03/16/9979112.aspx // why have this to begin with? http://blogs.msdn.com/b/oldnewthing/archive/2010/03/16/9979112.aspx
BOOL handleParentMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult) BOOL handleParentMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
{ {
@ -117,10 +134,12 @@ BOOL handleParentMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LR
case WM_CTLCOLORBTN: case WM_CTLCOLORBTN:
if (parentBrush != NULL) if (parentBrush != NULL)
if (DeleteObject(parentBrush) == 0) if (DeleteObject(parentBrush) == 0)
logLastError("error deleting old background brush in containerWndProc()"); logLastError(L"error deleting old background brush()"); // but continue anyway; we will leak a brush but whatever
if (SetBkMode((HDC) wParam, TRANSPARENT) == 0) if (SetBkMode((HDC) wParam, TRANSPARENT) == 0)
logLastError("error setting transparent background mode to controls in containerWndProc()"); logLastError(L"error setting transparent background mode to controls"); // but continue anyway; text will be wrong
parentBrush = getControlBackgroundBrush((HWND) lParam, (HDC) wParam); parentBrush = getControlBackgroundBrush((HWND) lParam, (HDC) wParam);
if (parentBrush == NULL) // failed; just do default behavior
return FALSE;
*lResult = (LRESULT) parentBrush; *lResult = (LRESULT) parentBrush;
return TRUE; return TRUE;
} }

View File

@ -63,3 +63,7 @@ extern void uninitUtilWindow(void);
// main.cpp // main.cpp
extern void registerMessageFilter(void); extern void registerMessageFilter(void);
extern void unregisterMessageFilter(void); extern void unregisterMessageFilter(void);
// parent.cpp
extern void paintContainerBackground(HWND hwnd, HDC dc, RECT *paintRect);
extern BOOL handleParentMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult);