Archive > Archived Posts

CWindow GroupBox

(1/2) > >>

James C. Fuller:
Jose,
  I assumed adding a groupbox would be the same as adding a button it appears I missed something.
My groupbox background is not the same color as the Window. I noticed in your CSED editor that groupboxes  you use do have the same background.

James


--- Code: ---#COMPILE EXE
#DIM ALL
%UNICODE = 1

' // Include files for external files
%USEXPBUTTON = 1
#INCLUDE ONCE "CWindow.inc"   ' // CWindow class

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Create an instance of the class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   ' // Note: CW_USEDEFAULT is used as the default value When passing 0's as the width and height
   pWindow.CreateWindow(%NULL, "CWindow with an XPButton", 0, 0, 500, 350, -1, -1, CODEPTR(WindowProc))

   ' // Center the window
   pWindow.CenterWindow

   ' // Add a button
   pWindow.AddXPButton(pWindow.hwnd, %IDCANCEL, "&Close", 350, 250, 75, 23, -1, -1)

   pWindow.AddGroupBox(pWindow.hwnd,-1,"Group #1",16,16,200,100,-1)
  

   ' // Default message pump (you can replace it with your own)
   pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   ' // Process window mesages
   SELECT CASE uMsg

      CASE %WM_COMMAND
         SELECT CASE LO(WORD, wParam)
            CASE %IDCANCEL
               ' // If the Escape key has been pressed...
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  ' // ... close the application by sending a WM_CLOSE message
                  SendMessage hwnd, %WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE %WM_DESTROY
         ' // End the application
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


--- End code ---

José Roca:
 
The default styles for the main window are %WS_OVERLAPPEDWINDOW OR %WS_CLIPCHILDREN OR %WS_CLIPSIBLINGS. The WS_CLIPCHILDREN style causes a window to exclude the areas occupied by child windows when the window paints its client area. However, a BS_GROUPBOX style window is a static control that never erases its background. Erasing the background removes any controls or buttons that appear within the group box.

Therefore, use %WS_OVERLAPPEDWINDOW OR %WS_CLIPSIBLINGS instead of -1


--- Code: ---pWindow.CreateWindow(%NULL, "CWindow with an XPButton", 0, 0, 500, 350, %WS_OVERLAPPEDWINDOW OR %WS_CLIPSIBLINGS, -1, CODEPTR(WindowProc))

--- End code ---

or subclass the groupbox and erase its background.

See: http://support.microsoft.com/kb/79982

Dominic Mitchell:
Sometimes one has to wonder about some of the articles in the Microsoft Knowledge Base.
That article is out of date and uses terms that are misleading.

The groupbox belongs to the "Button" class not the "Static" class.

The solutions to this problem range from fiddling with window styles to rolling your own groupbox.
My favourite solution is number 2. It is simple and handles the WS_CLIPSIBLINGS style(resizeable windows).

Note: the groupbox should be created after the controls it groups when the controls
on the parent have the WS_CLIPSIBLINGS style.

Solution 1 - no WS_CLIPCHILDREN style

This solution creates the parent window without the WS_CLIPCHILDREN style. This works fine on windows
that are not resizeable, but can cause nasty flickering on ones that are resizeable.

Solution 2 - add WS_EX_TRANSPARENT extended style

This solution keeps the WS_CLIPCHILDREN style on the parent window and adds the WS_EX_TRANSPARENT extended
window style to the groupbox. This works well on both nonresizeable and resizeable windows.
Also, flickering is significantly reduced.

Solution 3 - paint background
This solution keeps the WS_CLIPCHILDREN style on the parent window and subclasses the groupbox in order
to paint it background.
This works well on both nonresizeable and resizeable windows.  Also, flickering is significantly reduced.


--- Code: ---'-------------------------------------------------------------------------------
'
' PROCEDURE: Form1_Group1_SubclassProc
' PURPOSE:   Processes messages for the subclassed Button window.
'
'-------------------------------------------------------------------------------

FUNCTION Form1_Group1_SubclassProc _
  ( _
  BYVAL hWnd    AS DWORD, _ ' control handle
  BYVAL uMsg    AS DWORD, _ ' type of message
  BYVAL wParam  AS DWORD, _ ' first message parameter
  BYVAL lParam  AS LONG _   ' second message parameter
  ) EXPORT AS LONG

  LOCAL trc             AS RECT
  LOCAL lpOldWndProc    AS DWORD    ' address of original window procedure
  LOCAL lMsgResult      AS LONG     ' value returned to message after message is processed

  lpOldWndProc = GetProp(hWnd, "OLDWNDPROC")

  SELECT CASE uMsg
    CASE %WM_DESTROY
      ' Remove control subclassing
      SetWindowLong hWnd, %GWL_WNDPROC, RemoveProp(hWnd, "OLDWNDPROC")

    CASE %WM_ERASEBKGND
      GetClientRect hWnd, trc
      FillRect hDC, trc, GetClassLong(GetParent(hWnd), %GCL_HBRBACKGROUND)
      ' The message was processed
      FUNCTION = %TRUE     
      EXIT FUNCTION
  END SELECT

  FUNCTION = CallWindowProc(lpOldWndProc, hWnd, uMsg, wParam, lParam)

END FUNCTION

--- End code ---


Solution 4 - roll your own
A groupbox is a very simple control(read easy to write).
This solution will eliminate flicker.

Dominic Mitchell:
By the way, adding the WS_EX_COMPOSITED style to the parent or to the parent and children significantly reduces flicker or eliminates it.
But this is an extended style that needs to be checked against various controls before adding  it willy-nilly.

José Roca:
 
Thanks very much for your detailed information. Very useful, as always. For a quick fix, I will add the WS_EX_TRANSPARENT style as the default. Later, maybe I will write a custom control. This one looks nice: http://www.codeproject.com/KB/miscctrl/XGroupBox.aspx

Navigation

[0] Message Index

[#] Next page

Go to full version