0

I'm trying to manipulating a remote window in another process. I create a wrapper class of CWnd, and am trying to make constructor & copy constructor. So my application may have multiple instances of wrapper class attaching same HWND.

The error says:

Debug Assertion Failed!

Here is the sample code:

CWnd wnd1, wnd2;
wnd1.Attach((HWND)1);
wnd2.Attach((HWND)1); // Error happens in this line
IInspectable
  • 46,945
  • 8
  • 85
  • 181
user1633272
  • 2,007
  • 5
  • 25
  • 48
  • Is that literally what you're trying to do? Cast a constant value to a handle? – Andon M. Coleman Oct 19 '16 at 08:31
  • That's just an example. I believe it happens with real HWND too. – user1633272 Oct 19 '16 at 08:39
  • Please show your `CWnd` class. Also note that `HWND`s are not reference counted, so if multiple wrappers hold on to the same object, they must be able to negotiate ownership to ensure the `HWND` is not destroyed early. – andlabs Oct 19 '16 at 10:05
  • @andlabs `CWnd` is part of MFC – David Heffernan Oct 19 '16 at 10:11
  • You are trying to use a tool for something it wasn't meant to be used for. If you need real help, ask about your real problem, instead of what you believe to be your solution (TL;DR: this ain't). – IInspectable Oct 19 '16 at 11:16
  • The real problem is I'm trying to reduce the complexity of Win32 API calls by leveraging CWnd. – user1633272 Oct 19 '16 at 12:25
  • @user1633272: Unless you have a solid grip on the Windows API (and I mean **solid**), any MFC code you add will increase the complexity. Besides that, you are abusing MFC here. `Attach` takes ownership. And you're using it for an object you do **not** own. That's just wrong from the get-go, and it can only go downhill from there. – IInspectable Oct 19 '16 at 12:47
  • So wait, if you're using MFC why did you say you were creating a new class called `CWnd` with new constructors and so on? – andlabs Oct 19 '16 at 14:35
  • A wrapper class on top of CWnd to mange remote HWND by leveraging MFC CWnd - that's the initial idea. – user1633272 Oct 19 '16 at 14:40
  • Without knowing your objective I would still say that messaging between your processes is the solution you are looking for. It is much more robust than trying to access a shared object. That the window belongs to 'another' process implies that both processes will be making changes in an unordered manor. Chaos will be the result. Messaging between processes will lead to orderly results and make the evolution of your application much simpler. – lakeweb Oct 19 '16 at 15:45

1 Answers1

5

MFC is (in part) a resource management wrapper around the Windows API. It maintains a strict ownership relation between HWNDs and CWnds. A native HWND can only ever be owned by at most one CWnd object1.

That explains the error you get.

Now on to the solution: Since you do not own the foreign HWND anyway, attaching it to a CWnd is the wrong approach already. And since a CWnd merely offers resource management (which you don't need for resources you don't own), it doesn't buy you anything.

Solution: Drop MFC. Use the HWND with the Windows API.


1 MFC checks this invariant by keeping a list of all HWNDs, that are currently attached to CWnd objects. CWnd::FromHandlePermanent is a lookup into that list. If it returns a non-NULL value, the assertion fires.
IInspectable
  • 46,945
  • 8
  • 85
  • 181
  • I have a potential *solution* now, the wrapper class holds the HWND, and expose a method like this: CWnd* GetWnd() { return CWnd::FromHandle(innerHandle); } It works so far so good. – user1633272 Oct 19 '16 at 12:20
  • @user1633272: This is certainly not a solution, nor even a potential solution. Don't fumble with ownership of objects you don't own. – IInspectable Oct 19 '16 at 12:48
  • Thanks for your help. The MSDN document doesn't say CWnd::FromHandle shouldn't be used for remote HWND. I guess it's a mystery how windows API works underlying. Maybe the question could be: can we use CWnd to manage remote HWND? :) – user1633272 Oct 19 '16 at 14:08
  • @user1633272: It's only a mystery to those that skipped introducing themselves to the axiomatic ground rules. One of those ground rules is: `HWND`s have thread affinity, and should only be manipulated from their owning thread. Another such ground rule is, that MFC classes **own** resources. Yet another ground rule is that you should not use a class that models strict ownership for something you do not own. Doing so is denying logic. That's futile. (Don't use what you don't understand. That means the Windows API **and** MFC in your case.) – IInspectable Oct 19 '16 at 14:13
  • @user1633272: The answer to the question you haven't asked is: *"No, you should not ever attempt to use MFC, without **intimate** knowledge of the Windows API."* - I believe I've stated this on numerous occasions already, but you don't seem to quite grasp it. Have a look at [Prerequisites for learning MFC programming](http://stackoverflow.com/q/18165076/1889329) to put things into perspective for you. At that point you will understand, that MFC is not an appropriate tool for whatever you are trying to accomplish. – IInspectable Oct 19 '16 at 14:16