Solved

Insert Button into a window

Posted on 1997-11-21
21
277 Views
Last Modified: 2013-12-03

I created a window and painting lines and text on it's DC ,
I need to insert standard windows controls too , like buttons
and text boxs , this is not easy , when adding the control
the entire window recieves WM_PAINT , and the control (radio
button for example) won't paint until I press the space where
it should be displayed , what am I doing wrong ?

this is my program data:

windows class styles : CS_OWNDC | CS_DBLCLKS

window styles           : WS_OVERLAPPEDWINDOW

when WM_PAINT

      BeginPaint...

      hdc = ...

      ....paint...

      EndPaint


when other painting (not WM_PAINT)

      GetDC

      ....paint...

      ReleaseDC


0
Comment
Question by:moshem
21 Comments
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1408687
There are a couple of things. First, if you use children control on a window, you have to make sure that the parent window does not draw all over the children (unless that is the behavior you want, in which case this question is moot). If this is NOT the behavior you want, then you need to use the WS_CLIPCHILDREN window style on the parent window. This will automatically clip the children's rectangles away from the DC you get so that you can't draw on top of the children.

2. To force any window to repaint, you can use
 ::InvalidateRect(hwnd, NULL, TRUE);
 ::UpdateWindow(hwnd);


0
 
LVL 1

Author Comment

by:moshem
ID: 1408688
I tried it but it did not work !

I have a window , that I control display of the client area using GDI , I create the window like this :

      hWnd = CreateWindow (                              
      "DSCWNDCLASS",          
      "",
      WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN   ,
      100, 50, 800, 500,
      NULL,              
      NULL,              
      hMyInstance,          
      NULL);

then when this main window Get's WM_PAINT , I get it , get a DC and then Pass that DC to an OnPaint for each of the elements in my window (child windows) who are wrapped in a c++ class , so when I get paint , I check to see if I allready created the window , if so , I call UpdateWindow , if not I create the window like that :


      hWndEdit = CreateWindow (                              
      "BUTTON",          
      "",
      WS_CHILD |  WS_BORDER | WS_VISIBLE  | BS_NOTIFY | BS_RADIOBUTTON | BS_AUTORADIOBUTTON | BS_PUSHLIKE | BS_BITMAP ,
      pX, pY, pWidth, pHeight ,
      pMyParent->GetHWND(),              
      NULL,              
      pMyParent->GetInstance(),          
      NULL);


still , the only thing appears on my screen is the border of
the button and only if I press the button then it will paint it
self , also I suspect that creating the child yields another WM_PAINT to the parent and from there to all other children..

any idea?
0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1408689
Wait a minute! Are you saying that you are calling OnPaint for each of your children? That's not correct, you do not need to call OnPaint for each of your children. Windows will do that as necessary. If you remove the code that calls OnPaint for the children, do things work better?


0
 
LVL 1

Author Comment

by:moshem
ID: 1408690
my c++ framework was design to have one parent window and a few children windows or element such as text and grids , so when
the main window need to be painted it calls a paint method for all the children , some of them are windows (like button) in case of a button I don't do any painting but I do call Updatewindow , but even if I wont do anything it still gets the same problems...
0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1408691
Then, I would suspect the code for the button is probably getting the wrong rectangle to repaint. It is really hard to figure out what is happening here without some clue about the code.


0
 
LVL 1

Author Comment

by:moshem
ID: 1408692
sorry thui , you gave some clues but no answer , if you have
anything to add , please take the question again

Thanks
0
 
LVL 1

Author Comment

by:moshem
ID: 1408693
Adjusted points to 250
0
 

Expert Comment

by:pangofil
ID: 1408694
Send me your source and I'll fix it
0
 
LVL 1

Author Comment

by:moshem
ID: 1408695
I can't send you my source for many reasons ,
but you can tell me what you think and I will check it ,
what's wrong with that way?
0
 

Expert Comment

by:JeffNapier
ID: 1408696
Hi Moshem,
    One of my favorite solutions to a problem I can't figure out is to design a work-around instead.  Since I haven't seen your source code, I don't understand the problem entirely, but I think this will help:
     
    Rather than invoking a child window (control) within your main window, how about creating your own control.  For instance, if you want a button which is hexagonal instead of rectangular, you can draw it in the parent window's response to WM_PAINT, and respond to it in the parent window's response to WM_LBUTTONDOWN.  Of course you have to check the position of the mouse to see if the user clicked on your button and then respond accordingly.
 
    By the way, I can understand your reluctance about posting your source code. It might contain some very good technology that you don't want to give away. What you might do in a situation like this is to make a tiny little program which does nothing except show the problem, and post the source code to that.  

    I hope my work-around helps you out! - Jeff -
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 1

Author Comment

by:moshem
ID: 1408697
thanks for the answer , but that hardly answers my question , this solution is possible , but why ? when I can use ready-made
controls ? , to answer my question and simulate my condition
all you have to do , is create a window , then in response to
a **second** WM_PAINT message (not the first when created) add a child button control (window) , and see if it paints , when  it won't , you can tell me how you solved it and get your points

OK ?

thanks
Moshe
0
 
LVL 1

Author Comment

by:moshem
ID: 1408698
for all who want's to see the code that won't work , compile
and run this :


#include <windows.h>

BOOL CALLBACK WindowProc( HWND hWnd , UINT uMsg ,WPARAM wParam, LPARAM lParam );

int PASCAL WinMain(  HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszCmdLine,
                     int nCmdShow)
{
      HWND        hWnd;
      HWND        hWndEdit;
      HINSTANCE hMyInstance;

      hMyInstance = hInstance;


      WNDCLASS    wcMain;                                                // window class struct
                                                                        // fill window class struy
    wcMain.style = CS_OWNDC | CS_DBLCLKS  ;                    
    wcMain.lpfnWndProc = (WNDPROC)WindowProc;
    wcMain.cbClsExtra = 0;              
    wcMain.cbWndExtra = 0;              
    wcMain.hInstance = hMyInstance;      
    wcMain.hIcon = NULL;
    wcMain.hCursor = LoadCursor ( NULL , IDC_ARROW) ;
    wcMain.hbrBackground = (HBRUSH) GetStockObject ( WHITE_BRUSH);
    wcMain.lpszMenuName =  NULL;  
    wcMain.lpszClassName = "WNDCLASS";

      
    RegisterClass(&wcMain) ;                                  // register class


      hWnd = CreateWindow (                              
      "WNDCLASS",          
      "",
      WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN  | WS_VISIBLE ,
      100, 50, 800, 500,
      NULL,              
      NULL,              
      hMyInstance,          
      NULL);

//      if ( hWnd )
//            SetWindowLong ( hWnd , GWL_USERDATA , (LPARAM) this );


      ShowWindow ( hWnd , SW_SHOW );


      
      
      hWndEdit = CreateWindow (                              
      "BUTTON",          
      "",
      WS_CHILD |  WS_BORDER | WS_VISIBLE  | BS_NOTIFY | BS_RADIOBUTTON | BS_AUTORADIOBUTTON | BS_PUSHLIKE /*| BS_BITMAP */,
      30, 30, 50, 50 ,
      hWnd,              
      NULL,              
      hMyInstance,          
      NULL);


      ShowWindow ( hWndEdit , SW_SHOW );
      
      
      
      MSG msg;

      while ( GetMessage (&msg , NULL, 0, 0) )
      {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
      }
      
      return 1;


}




BOOL CALLBACK WindowProc( HWND hWnd , UINT uMsg ,WPARAM wParam, LPARAM lParam )
{

      switch(uMsg)
      {
            case WM_CREATE:

                  return 0;

            break;

            case WM_CLOSE:

            case WM_QUIT:

                  PostQuitMessage ( 0 );
                  return 1;

            break;

       }
   
   return DefWindowProc(hWnd, uMsg, wParam, lParam);

}



anyone can tell me why the child window won't paint ?
0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1408699
I have found the problem and the solution, but I want to make sure I get the credit because I did the work.
0
 
LVL 1

Author Comment

by:moshem
ID: 1408700
if u can make the above answer work it's yours , tell me that
it's so and I will reject the previous answer so you can
get the points !

Moshe
0
 
LVL 1

Author Comment

by:moshem
ID: 1408701
to thui : of course I mean make the above piece of code work !
sorry !
0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1408702
The problem is the style bits you're using for the button. Here are the bits as defined in Winuser.h:

#define BS_PUSHBUTTON       0x00000000L
#define BS_DEFPUSHBUTTON    0x00000001L
#define BS_CHECKBOX         0x00000002L
#define BS_AUTOCHECKBOX     0x00000003L
#define BS_RADIOBUTTON      0x00000004L
#define BS_3STATE           0x00000005L
#define BS_AUTO3STATE       0x00000006L
#define BS_GROUPBOX         0x00000007L
#define BS_USERBUTTON       0x00000008L
#define BS_AUTORADIOBUTTON  0x00000009L
#define BS_OWNERDRAW        0x0000000BL

The default is BS_PUSHBUTTON and in most cases, that's what you would want. However, if you do want any of the others from the above list, do note that are mutually exclusive, meaning you are NOT supposed to combine them together and if you do combine them, the behavior is undefined.

That's the problem in the code. If you comment out all of the BS_ style bits, you'll find the code works.

0
 
LVL 1

Author Comment

by:moshem
ID: 1408703
I don't get it ,
first I don't get "mutually exclusive" , please explain ,

second , I don't want a push button , I want a radio
button that works like a pushbutton ( ie.BS_PUSHLIKE) and
I want it to be owner-draw ( ie.BS_BITMAP) so how
can I achive that when I can't "combine" those , BTW
I have an resource based dialog that does the same
and it works!

please comment as soon as possible as this is very
urgent
0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1408704
Mutually exclusive means you have to choose either none or one, but not more than one.

That means your line of code that is

WS_CHILD | WS_BORDER | WS_VISIBLE | BS_NOTIFY | BS_RADIOBUTTON | BS_AUTORADIOBUTTON | BS_PUSHLIKE /*| BS_BITMAP */,

cannot work. It has to be WS_CHILD | WS_BORDER | WS_VISIBLE | BS_AUTORADIOBUTTON.

If you check the style for the dialog in the resource file, you'll see that its style are set in a certain way, then use that in place of the your existing code.
0
 
LVL 1

Author Comment

by:moshem
ID: 1408705
Dear Thui!

your answer worked , if you can please explain the term
"Mutually exclusive" in more detail , so I can know by
my self what defines are like that in the future.

in any case , I am rejecting the previous answer , so
please put your answer in and I will accept it.

Thanks!
0
 
LVL 15

Accepted Solution

by:
Tommy Hui earned 300 total points
ID: 1408706
Mutually exclusive means you can only use one and no more. There are some styles that are explicitly declared that way in the documentation. Others are implicitly mutually exclusive. You can usually know which ones they are if the bits are not a power of two.

This depends on the mathematics of powers of two. You can combine (logical or) any power of two and they won't add up to a power of two. However, if you have bits that are defined in numerical order, then combining those can and will add up to another flag. So there could be problems.

0
 
LVL 1

Author Comment

by:moshem
ID: 1408707
Thanks !
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

This article shows a few slightly more advanced techniques for Windows 7 gadget programming, including how to save and restore user settings for your gadget and how to populate the "details" panel that is displayed in the Windows 7 gadget gallery.  …
In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now