Solved

Capture Windows form paint messages

Posted on 2008-06-20
6
1,216 Views
Last Modified: 2013-12-03
Hi Experts

I have a  standard frame on a form with a background drawn via BitBlt.  The form is maximised and covers the whole desktop area but the frame is only covering a part of my form. If another application gets the focus (ie the user decides to switch apps) and is moved or resized over the frame, the background portion of the frame where the other application has overlayed it gets redrawn. The redrawn portion is painted with the background colour property colour and not my BitBlt  image.

What I want to do is either
a) detect that another app has focus and is redrawn, moved  or sized over my app (in particular over my frame but just over my app would be enough); or
b) detect that part of my frame has been redrawn.

Once I have this I will call a redraw of my frame backgound BitBlt to repair the portion redrawn because of the other app.

I do not understand enough about how Windows redraws the portion under an app that is resizing to know how to do this.

Looking for a subclass/hook solution or ideas on which windows message to look for. No timer stuff please.

Thanks in advance
Graeme
0
Comment
Question by:superg65
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
6 Comments
 
LVL 22

Expert Comment

by:danaseaman
ID: 21836671
Not sure how you BitBlt to Fram since it does not have hDc Properrty. Can you put a PictureBox on the Frame and draw to that instead? Set PictureBox AutoRedraw = True. If it doesn't persist try Picture1.refresh after BitBlt.
0
 
LVL 2

Author Comment

by:superg65
ID: 21839032
Hi danaseaman

You can create and assign a DC to a lightweight control using the API GetDC

Public Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
dim FrameDC as long
FrameDC = GetDC(fraFrame.hwnd)

Then just BitBlt using that DC.

This problem all comes about from me creating my own transparent frame as VB6 frames don't have transparency (I think the VB.Net stuff has transparent frames but I can't afford the .NET developer edition yet).

I tried some transparent frame activeXs and code off internet but none of them handle the transparency around the frame caption properly. The BitBlt version I created works really well except for the redraw if another app resizes/moves on top of it.

I looked at using a Picturebox in the frame but the frame caption is outside this so misses the transparent BitBlt.

If I can capture some sort of redraw message then can just BitBlt transparent again. Tried using a timer but then issues come up around capturing the background behind the frame again after form redraws. I'm not a fan of timers really - just don't like having code repeatedly firing on a timer event - hard to know what else is going on in a complicated app that the refiring code miight affect.

Am using subclassing to detect when my app loses focus to another app to do frame redraws on reactivation of app - all works fine - just this issue with the foreground window redrawing over my frames.

Cheers
G

0
 
LVL 2

Author Comment

by:superg65
ID: 21839153
Hi Again D

Been thinking a bit more about your PictureBox suggestion. What I haven't tried is BitBltiing the transparency to both the frame AND a picture box inside the frame (with the Picturebox covering the frame client area). Then might be able use the PictureBox to trigger redraws of the transparency on both - maybe throught the Paint event? Will give it a try but still interested in a subclass solution.

Thx
G
0
Salesforce Has Never Been Easier

Improve and reinforce salesforce training & adoption using WalkMe's digital adoption platform. Start saving on costly employee training by creating fast intuitive Walk-Thrus for Salesforce. Claim your Free Account Now

 
LVL 22

Expert Comment

by:danaseaman
ID: 21839191
Don't you need the hWnd to Subclass?

How about a Frame control that has hWnd, hDc, and AutoRedraw?

jcFrames control version 2.0.1jcFrames control version 2.0.1
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=64261&lngWId=1

Replacent Frame Control for XP
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=36043&lngWId=1

XP Style Frame (JCSR) as Usercontrol
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=63762&lngWId=1

drawing XP style frame on picturebox
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=63739&lngWId=1
0
 
LVL 17

Accepted Solution

by:
zzzzzooc earned 500 total points
ID: 21839549
Frames aren't meant for displaying backgrounds but if you really want to include that, it should be done through subclassing and not by adding more controls. Subclassing does add some instability but as long as your window-procedure isn't error-prone, it should cause minimal problems.

Here's a little example on how to subclass for WM_PAINT and WM_NCPAINT messages. Not sure which would suit your needs.



Form1:
---------------------
Private Sub Form_Load()
    Call Subclass(True, Frame1.hWnd)
End Sub
Private Sub Form_Unload(Cancel As Integer)
    Call Subclass(False, Frame1.hWnd)
End Sub


Module1:
--------------------
Option Explicit

Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hdc As Long) As Long

Private Const GWL_WNDPROC   As Long = -4

Private Const WM_PAINT  As Long = &HF
Private Const WM_NCPAINT As Long = &H85

Private lngPrevProc As Long
Public Sub Subclass(ByVal blnTrue As Boolean, ByVal hWnd As Long)
    If blnTrue = True Then
        lngPrevProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
    Else
        Call SetWindowLong(hWnd, GWL_WNDPROC, lngPrevProc)
    End If
End Sub
Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Select Case uMsg
        Case WM_PAINT
            'draw window.. uncomment the below if you don't want to completely
            'override the default window-procedure.
           
            'WindowProc = CallWindowProc(lngPrevProc, hWnd, uMsg, wParam, lParam)
        Case WM_NCPAINT
            'draw non-client area
            'hWnd: handle to window receiving msg (frame1)
            'wParam: handle to region (hRGN) specifying where to draw
            Debug.Print "nc"
        Case Else
            WindowProc = CallWindowProc(lngPrevProc, hWnd, uMsg, wParam, lParam)
    End Select
End Function
0
 
LVL 2

Author Closing Comment

by:superg65
ID: 31469381
Thanks - worked just as I needed.
G
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

707 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