Results 1 to 7 of 7

Thread: [VB6] Themes - Frames

  1. #1

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    [VB6] Themes - Frames

    Those that are familiar with VB, themes and controls on frames may find this information useful.
    Name:  results.PNG
Views: 6055
Size:  8.4 KB
    Background: Using manifest files, we can have many VB controls themed, even the frame control. However, controls that contain transparency do not render correctly in frame controls. Shown in the "after" & "before" images above.

    Solutions:
    1. The widely accepted solution is don't use frames to host controls that have these problems, mainly: command buttons & option buttons.
    2. Subclass the frame and trap/respond to a single message.

    In the image above, you can see black where the themed control is partially transparent. The reason why they paint black is because the Frame does not respond to WM_PRINTCLIENT messages. If we respond for the frame, all is good.

    The problem with using Frames with themes and only hosting controls that appear to draw fine is that it isn't future-proof. What happens if the new operating system themes checkboxes transparently? themes combo/listboxes with rounded corners? What used to look good in XP now doesn't in the new operating system. Subclassing helps ensure app looks good with future themes.

    Assuming you are familiar with subclassing, here would be a workable/resuable example. Just start subclassing your frame on form load. It is recommended to unsubclass it on form unload but is not absolutely necessary. Subclassing can cause crashes in IDE and the following should only be activated before compiling to be completely safe; use caution when subclassing in uncompiled projects.

    This code must be placed in a bas module, not a form, not a class.
    Code:
    Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
    Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare Function CallWindowProc Lib "user32.dll" 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 GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
    Private Declare Function GetProp Lib "user32.dll" Alias "GetPropA" (ByVal hWnd As Long, ByVal lpString As String) As Long
    Private Declare Function SetProp Lib "user32.dll" Alias "SetPropA" (ByVal hWnd As Long, ByVal lpString As String, ByVal hData As Long) As Long
    Private Declare Function DefWindowProc Lib "user32.dll" Alias "DefWindowProcA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Const WM_PRINTCLIENT As Long = &H318
    Private Const WM_PAINT As Long = &HF&
    Private Const GWL_WNDPROC As Long = -4
    Private Const WM_DESTROY As Long = &H2
    
    
    Public Sub SubclassFrame(FramehWnd As Long, ReleaseSubclass As Boolean)
        Dim prevProc As Long
    
        prevProc = GetProp(FramehWnd, "scPproc")
        If ReleaseSubclass Then
            If prevProc Then
                SetWindowLong FramehWnd, GWL_WNDPROC, prevProc
                SetProp FramehWnd, "scPproc", 0&
            End If
        ElseIf prevProc = 0& Then 
            SetProp FramehWnd, "scPproc", GetWindowLong(FramehWnd, GWL_WNDPROC)
            SetWindowLong FramehWnd, GWL_WNDPROC, AddressOf WndProc_Frame
        End If
    End Sub
    
    Private Function WndProc_Frame(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        
        Dim prevProc As Long
        
        prevProc = GetProp(hWnd, "scPproc")
        If prevProc = 0& Then
            WndProc_Frame = DefWindowProc(hWnd, uMsg, wParam, lParam)
        ElseIf uMsg = WM_PRINTCLIENT Then
            SendMessage hWnd, WM_PAINT, wParam, ByVal 0&
        Else
            If uMsg = WM_DESTROY Then SubclassFrame hWnd, True
            WndProc_Frame = CallWindowProc(prevProc, hWnd, uMsg, wParam, lParam)
        End If
    End Function
    Edited: Note that the frame issue isn't just with frames, it applies to forms, pictureboxes and any VB container really, but not exactly in the same way. Don't know if you ever noticed, but add an option button on your form that overlaps an image. Is the option button bkg transparent? It is in the example above. Add a command button over the image. Are the corners round and bkg transparent? It is in the above example. Adding command buttons and option buttons on a dark form background also highlights the problem. I don't know when WM_PRINTCLIENT was first implemented in Windows, but my guess is after VB was designed and VB service packs didn't appear to have implemented it (correctly or at all). You can use the same principle above for the form itself or a picturebox control too. If subclassing a form, definitely recommend unsubclassing it on form unload.

    P.S. Regarding transparent bkg on the option button; not sure if a pure API option button is also transparent -- haven't tested it.

    Edited: There are 2 ways to included manifests with a compiled application. In this other project of mine, description and creation of manifests, both ways, can be found.
    Last edited by LaVolpe; Apr 23rd, 2010 at 03:55 PM. Reason: tweaked the subclass routine to make it more fool-proof
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  2. #2
    Fanatic Member BenJones's Avatar
    Join Date
    Mar 2010
    Location
    Wales UK
    Posts
    814

    Re: [VB6] Themes - Frames

    Looks cool thanks for shareing with us

  3. #3
    New Member Bayu Malmsteen's Avatar
    Join Date
    Apr 2010
    Location
    Bandung, Indonesia
    Posts
    14

    Re: [VB6] Themes - Frames

    for controls into the frames...to make it change with themes normally, it's very simple you can adding with picturebox into frame and then in the picturebox you add that controls such as combobox, checkbox and button, and then compile it, you will see...the button and checkbox is change with normally...that's all..

  4. #4

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] Themes - Frames

    Quote Originally Posted by Bayu Malmsteen View Post
    for controls into the frames...to make it change with themes normally, it's very simple you can adding with picturebox into frame and then in the picturebox you add that controls such as combobox, checkbox and button, and then compile it, you will see...the button and checkbox is change with normally...that's all..
    Sure, you've also just added an unnecessary window to your application. But that should be listed as Option #3 in my first post.

    Edited:
    But the problems still remain. Make your picturebox backcolor black and add a button, compile, apply manifest and see that the button does not show blended rounded corners. Subclassing is the correct method in my opinion, but still not perfect. Even responding to the WM_PRINTCLIENT message for the container, it doesn't draw perfectly and this I believe is a flaw in the way common controls library tries to theme VB intrinsic controls.
    Last edited by LaVolpe; Apr 27th, 2010 at 03:03 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5
    New Member MrSmith.'s Avatar
    Join Date
    Nov 2009
    Posts
    14

    Re: [VB6] Themes - Frames

    Nice code LaVolpe Thanks

  6. #6
    Addicted Member
    Join Date
    Jun 2010
    Posts
    208

    Re: [VB6] Themes - Frames

    Thanks for nice code, but if I want to subclass a picture box the same way, what exactly in the code above would change or the same code would work "as is"?

  7. #7

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] Themes - Frames

    7edm: the code can be tweaked to subclass any window. Obviously you will want to modify the WndProc_Frame routine to view/modify whatever messages are of interest. Please post additional questions in the appropriate forum (VB6, .Net, etc).
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width