No announcement yet.

Can BeginPaint Be Used On Desktop?

  • Filter
  • Time
  • Show
Clear All
new posts

  • Can BeginPaint Be Used On Desktop?

    In WM_PAINT I try to draw on the desktop. The code, using BeginPaint doesn't work.

    I can use similar code in a button-press, but with GetDC, the code successfully draws on the Desktop.
    Is there a problem with feeding BeginPaint a handle to the Desktop? Or is there some other reason why the code won't work?

    I also noticed that I cannot force the Desktop to redraw using UpdateWindow. I'm not sure why that doesn't work either.

    I know the result won't be persistent.

    Here's the compilable example:
    'Compilable Example:
    #Compile Exe
    #Dim All
    #Include ""
    Global hDlg as DWord, hWnd as DWord, hDC as DWord, PS as PaintStruct
    Function PBMain() As Long
       Dialog New Pixels, 0, "Test Code",300,300,200,200, %WS_OverlappedWindow To hDlg
       Control Add Button, hDlg, 100,"Draw", 50,10,100,20
       Control Add Button, hDlg, 101,"Redraw", 50,40,100,20
       Dialog Show Modal hDlg Call DlgProc
    End Function
    CallBack Function DlgProc() As Long
       Select Case CB.Msg
          Case %WM_Paint
             hWnd = GetDesktopWindow           'the Desktop is a window too!
             hDC = BeginPaint(hWnd, PS)        'get a handle to the Desktop's DC
             Ellipse hDC, 100,100,300,300      'draws a circle on the Desktop surface
             EndPaint hDC, PS                  'releases the handle to the Desktop DC
       End Select
       If CB.Msg = %WM_Command AND CB.Ctl = 100 AND CB.Ctlmsg = %BN_Clicked Then
          hWnd = GetDesktopWindow           'the Desktop is a window too!
          hDC = GetDC(hWnd)                 'get a handle to a Desktop's DC
          Ellipse hDC, 100,100,300,300      'draws a circle on the Desktop surface
          ReleaseDC hWnd,hDC                'releases the handle to the Desktop DC
       End If
       If CB.Msg = %WM_Command AND CB.Ctl = 101 AND CB.Ctlmsg = %BN_Clicked Then
          hWnd = GetDesktopWindow           'the Desktop is a window too!
          UpdateWindow hWnd
       End If
    End Function
    Last edited by Gary Beene; 7 Jan 2010, 06:59 PM.

  • #2
    Well, I may not know which API does the trick, but I did recall this line of code that causes the Desktop to update.

    Dialog ReDraw %NULL
    This code was a mistake I made that caused the desktop to flicker in one of my apps. Nice to see it could actually be used for something good.


    • #3
      RedrawWindow does the trick:



      • #4
        Jose, thanks!

        I had read that RedrawWindow with %NULL could also be used, but it seemed like overkill, plus I didn't know exactly which constants were needed to fill the arguments. Your line of code fits the need!


        • #5
          I believe your use of beginpaint is highly improper!

          While it is true that beginpaint passes a window handle as a parameter, it is assumed that the window handle passed is the one that generated the WM_PAINT message. Your passing the desktop window handle instead is highly out of character for proper coding of a WM_PAINT message.

          The DeskTop itself has its own window procedure which processes WM_PAINT for itself. You should not be attempting to process the WM_PAINT message for one window (your dialog) by drawing into another.

          Now you can draw onto another window outside of WM_PAINT by using GetDC, which is a common technique.

          I find that it is not a good habit to do things differently than what is considered normal windows API coding.
          Chris Boss
          Computer Workshop
          Developer of "EZGUI"


          • #6
            hDCdest = GetWindowDC(GetDesktopWindow())
            CALL skAlphaBlend(hDCdest, 0, 0, nWidth, nHeight, hDCsrce, 0, 0, nWidth, nHeight)
            CALL ReleaseDC(GetDesktopWindow(), hDCdest)
            However when you need to draw something onto the desktop, there is a much better technique that is based on the use of UpdateLayeredWindow in conjunction with the %WS_EX_LAYERED extended style. I have explained this on José Roca's forum. See also the GDImage "OfTheBay" dockbar project that is based on the same concept. And see also the Boing demo.
            Last edited by Patrice Terrier; 8 Jan 2010, 01:42 AM.
            Patrice Terrier
            Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).


            • #7
              Thanks for the comments.

              So you're saying that the 'proper' coding is that BeginPaint should always get the handle for the dialog. Then, if I want to write only on a control, for example, that I should use GetDC within the BeginPaint/EndPaint code to acquire and use the DC for the control.

              Even though what you say sounds like good cautionary coding, I must say that I didn't see any such restrictions suggested in MSDN. I especially did not see something that matches what you wrote:

              ... it is assumed that the window handle passed is the one that generated the WM_PAINT message.
              I did see the MSDN comment that:

              An application should not call BeginPaint except in response to a WM_PAINT message.
              The point is that your cautions are certainly consistent with the idea that there are limitations on the use of BeginPaint. Until I read the quote above, I assumed I could call BeginPaint anywhere in code that I wanted (don't know why I would want to , but I actually tried it in a button press and it didn't work).

              The requirement for BeginPaint to receive the dialog handle wouldn't be the first time MSDN failed to include an important nuance in their API documentation. Can you point to any reference material that talks to that limitation? I'd like to learn more about the topic.

              Now that you've raised my awareness of the issue, I'll head over to the Petzold and Rector books and read their comments as well.

              Even though it (the fact itself, not that you stated it) irks me somewhat, you make a good point with your comment:

              I find that it is not a good habit to do things differently than what is considered normal windows API coding.
              First of all, who's the arbiter on normal coding? Secondly, despite my tendency to play loose with the 'rules', when it comes to production coding I am forced to agree with your sentiment.

              I would rather MS tell me what will happen if I do something, rather than simply tell me it's good practice not to do it. I then get to vote whether to do it or not, taking a known risk. I find that MSDN documentation sometimes says "don't", but doesn't always tell me what will happen if I do, so I don't clearly understand the risk of doing it anyway.
              Last edited by Gary Beene; 8 Jan 2010, 07:59 PM.


              • #8

                Every different window type (called a window class) has its own window procedure which is where WM_PAINT is processed.

                Dialogs have the unique feature of being able to forward the messages from there window procedure (which is located in the operating system itself) to a Dialog procedure, so when you process WM_PAINT in a dialog procedure it is the same as processing it in the dialogs window procedure.

                Controls also have their own window procedures, but they are located in the operating system. To get access to their window procedure requires subclassing, which is a form of forwarding messages to a different window procedure. Once subclassed, you can process a controls WM_PAINT message.

                BeginPaint must be called in WM_PAINT. It works differently than does GetDC. For example it gets the cliiping rectangle so you can draw only what needs to be drawn.

                What you were doing was getting the handle to a window other than the one associated with the dialog procedure and passing that handle to beginPaint, which is a "NO NO" IMO. Windows assumes you are passing the window handle of the same window as the window procedure processing WM_PAINT.

                Now one can draw outside of WM_PAINT, even on other windows, such as the desktop using GetDC, but that is different than processing WM_PAINT.

                It is important to remember that just because Windows may tolerate improper calls being made, this does not mean it is alright to do and has no consequences.

                Now if you can find some example code on MSDN (Microsofts developer web site) demonstrating the technique you tried, that may give one reason to try it, but I doubt you will.

                As far as "normal" coding, I am not refering to some persons view of what is normal coding, but rules based on the Windows API docs.
                Sady the API docs don't spell out every "do not do" scenario, such as the one you are doing.
                They do though give example code in how to write routines correctly and all the examples I have ever scene pass the same window handle to beginpaint as the one passed to the window or dialog procedure.

                Like I said, if you can find an example of what you are doing on MSDN, then "maybe" it is acceptable, but I doubt it very much.

                Lastly, I would like to say that the Windows API is not as flexible as some may think and things do need to be done exactly as Microsoft outlines them.
                There are rules, some spelled out, some assumed, but none the less there are rules.

                Breaking those rules is what makes Windows software unreliable.

                Do not simply experiment and try stuff, just because it appears possible. That spells disaster in Windows.
                One version of the operating system may tolerate some breaking of the rules, but another version may crash because of it.

                I strongly recommend all PB'ers who write API code to purchase (CD) or download the latest Windows SDK. Its big and the docs are extensive, but worth having.
                I double check every API function or message I used with the API docs. I also search MSDN for example code at times when I need more clarification.
                Last edited by Chris Boss; 8 Jan 2010, 08:33 PM.
                Chris Boss
                Computer Workshop
                Developer of "EZGUI"


                • #9
                  The short answer is that how you use the Windows API is not strictly defined (also contains a few pitfalls), so some aspects can be open to interpretation. For the newer APIs, it can be difficult to get things working across the different versions of Windows, but for the established APIs, there is plenty of experience and it's not hard to find working examples that people have posted. The Rector/Newcomer "Programming Win32" book also highlights pitfalls in the API

                  From over 12 years of my experience programming in Windows, I learnt that going against the grain and using backdoor tricks or hacks, you usually come unstuck later on when your bells & whistles app doesn't function on a later version of Windows (or one that is configured differently). Even worse if it destroys data or deletes system files. So I found it's better to play safe and follow the code others have posted (or ask) if I don't know, and if someone says "don't do that", it's usually wise not to.
                  Last edited by Kev Peel; 8 Jan 2010, 09:38 PM.
         | Slam DBMS | PrpT Control | Other Downloads | Contact Me