Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. MFC Regular DLLs and Handle Maps

MFC Regular DLLs and Handle Maps

Scheduled Pinned Locked Moved C / C++ / MFC
tutorialworkspacec++jsonhelp
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Dave Glick
    wrote on last edited by
    #1

    Hi all, I've got a very difficult problem that I've spent several weeks trying to figure out. I think I finnaly know the issues, but not how to solve them. I humbley submit my predicament to you fine folks here on code project to see if anyone has any insight... Let me describe the setup: -I have a MFC regular DLL statically linked to MFC (I don't know what language or environment my DLL will be used from and I want to support the broadest range). -This DLL globaly subclasses certain types of GUI objects. For the purpose of providing an example, I'll use the windows BUTTON api class for illustration here. -The DLL calls ::SetClassLong and does some mumbo-jumbo to override all BUTTON WndProcs and set them to be ownerdrawn. At the same time, I subclass all of them to a special CoolButton class derived from the MFC CButton. -I also subclass all Dialogs so that I can intercept WM_DRAWITEM messages and send them to the child based on my handle map rather than the app's (because the app doesn't know about my subclassed CoolButtons, it would send the DrawItem message to CButtons which would assert because the DrawItem function hasn't been overridden). Everyone still with me :) Everything works perfectly from other languages and from within MFC except in one case, and this is the root of the problem: When a button on a dialog has had a member variable of type CButton declared from within the calling application, I ASSERT on a call to CButton::DrawItem (because no override is present) at random times (for example right after a WM_KILLFOCUS message). I think this happens because the message pump looks like this: -Send WM_KILLFOCUS to the AfxWndProc -AfxWndProc sends it down the pipe -I intercept (remember I'm looking for WM_DRAWITEM messages for the parent so I've inserted myself here) -I want to do the default action, so I pass the WM_FILLFOCUS to the old WndProc (which I got from my call to ::SetClassLong) -The old WndProc does the default OnKillFocus action - everything works great up to here. -If no member CButton variable has been declared, the old WndProc sends a WM_DRAWITEM to the parent, I intercept it, take action, and viola, everything works great! If a member CButton has been declared, the default WndProc bypasses the top level windows message routing routine, I never see the WM_DRAWITEM message, and by looking up the CButton member from the application's permanent handle map it calls the CButton::DrawItem and I crash :( The solution, as I see it, is to replace the CButton member variab

    T 1 Reply Last reply
    0
    • D Dave Glick

      Hi all, I've got a very difficult problem that I've spent several weeks trying to figure out. I think I finnaly know the issues, but not how to solve them. I humbley submit my predicament to you fine folks here on code project to see if anyone has any insight... Let me describe the setup: -I have a MFC regular DLL statically linked to MFC (I don't know what language or environment my DLL will be used from and I want to support the broadest range). -This DLL globaly subclasses certain types of GUI objects. For the purpose of providing an example, I'll use the windows BUTTON api class for illustration here. -The DLL calls ::SetClassLong and does some mumbo-jumbo to override all BUTTON WndProcs and set them to be ownerdrawn. At the same time, I subclass all of them to a special CoolButton class derived from the MFC CButton. -I also subclass all Dialogs so that I can intercept WM_DRAWITEM messages and send them to the child based on my handle map rather than the app's (because the app doesn't know about my subclassed CoolButtons, it would send the DrawItem message to CButtons which would assert because the DrawItem function hasn't been overridden). Everyone still with me :) Everything works perfectly from other languages and from within MFC except in one case, and this is the root of the problem: When a button on a dialog has had a member variable of type CButton declared from within the calling application, I ASSERT on a call to CButton::DrawItem (because no override is present) at random times (for example right after a WM_KILLFOCUS message). I think this happens because the message pump looks like this: -Send WM_KILLFOCUS to the AfxWndProc -AfxWndProc sends it down the pipe -I intercept (remember I'm looking for WM_DRAWITEM messages for the parent so I've inserted myself here) -I want to do the default action, so I pass the WM_FILLFOCUS to the old WndProc (which I got from my call to ::SetClassLong) -The old WndProc does the default OnKillFocus action - everything works great up to here. -If no member CButton variable has been declared, the old WndProc sends a WM_DRAWITEM to the parent, I intercept it, take action, and viola, everything works great! If a member CButton has been declared, the default WndProc bypasses the top level windows message routing routine, I never see the WM_DRAWITEM message, and by looking up the CButton member from the application's permanent handle map it calls the CButton::DrawItem and I crash :( The solution, as I see it, is to replace the CButton member variab

      T Offline
      T Offline
      Tomasz Sowinski
      wrote on last edited by
      #2

      Dave Glick wrote: The DLL calls ::SetClassLong and does some mumbo-jumbo to override all BUTTON WndProcs and set them to be ownerdrawn. At the same time, I subclass all of them to a special CoolButton class derived from the MFC CButton Could you describe this step in more detailed fashion? Dave Glick wrote: I think this happens because the message pump looks like this: -Send WM_KILLFOCUS to the AfxWndProc WM_KILLFOCUS is sent (not posted through message loop/pump). Tomasz Sowinski -- http://www.shooltz.com

      D 1 Reply Last reply
      0
      • T Tomasz Sowinski

        Dave Glick wrote: The DLL calls ::SetClassLong and does some mumbo-jumbo to override all BUTTON WndProcs and set them to be ownerdrawn. At the same time, I subclass all of them to a special CoolButton class derived from the MFC CButton Could you describe this step in more detailed fashion? Dave Glick wrote: I think this happens because the message pump looks like this: -Send WM_KILLFOCUS to the AfxWndProc WM_KILLFOCUS is sent (not posted through message loop/pump). Tomasz Sowinski -- http://www.shooltz.com

        D Offline
        D Offline
        Dave Glick
        wrote on last edited by
        #3

        Could you describe this step in more detailed fashion? Sure - First I have a LRESULT CALLBACK MyWndProc() function that I've set up to process messages, I'll describe it more specificaly in a moment. I create a CButton and then call ::SetClassLong using GCL_WNDPROC as the argument and then I store the return value for use in MyWndProc. Inside MyWndProc, I watch for WM_PAINT messages (because this is the first message that gets sent after MFC has actually added it's member variables to the permanent message map - and because after I subclass, WM_PAINT won't get sent anymore for my ownerdrawn buttons) and when I find one, I create a new CoolButton and tell it to subclass the Wnd. It's in this step that I would unattach the member CButton from the application's permanent message map if I had access to it (In fact, the unattach is essential if this code is to be run from the application itself since a handle map can not have two MFC classes pointing to the same window handle). Was this what you were looking for? WM_KILLFOCUS is sent (not posted through message loop/pump). My bad - in any case, it ends up going through my WndProc and then being sent on to the default one, which is what causes the crash when a member variable exists. Thanks, Dave

        T 1 Reply Last reply
        0
        • D Dave Glick

          Could you describe this step in more detailed fashion? Sure - First I have a LRESULT CALLBACK MyWndProc() function that I've set up to process messages, I'll describe it more specificaly in a moment. I create a CButton and then call ::SetClassLong using GCL_WNDPROC as the argument and then I store the return value for use in MyWndProc. Inside MyWndProc, I watch for WM_PAINT messages (because this is the first message that gets sent after MFC has actually added it's member variables to the permanent message map - and because after I subclass, WM_PAINT won't get sent anymore for my ownerdrawn buttons) and when I find one, I create a new CoolButton and tell it to subclass the Wnd. It's in this step that I would unattach the member CButton from the application's permanent message map if I had access to it (In fact, the unattach is essential if this code is to be run from the application itself since a handle map can not have two MFC classes pointing to the same window handle). Was this what you were looking for? WM_KILLFOCUS is sent (not posted through message loop/pump). My bad - in any case, it ends up going through my WndProc and then being sent on to the default one, which is what causes the crash when a member variable exists. Thanks, Dave

          T Offline
          T Offline
          Tomasz Sowinski
          wrote on last edited by
          #4

          I think the problem is too complicated to get it resolved via posting on the board. If it doesn't broke trade secrets, feel free to send me the sources :) Tomasz Sowinski -- http://www.shooltz.com

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups