Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You can call <code>CHFTAppBView::FromHandle(hWnd)</code> but what you get back isn't a pointer to a <code>CHFTAppBView</code>; it's a pointer to a <code>CWnd</code>. By casting it, you're telling the compiler "trust me, this is really a pointer to a <code>CHFTAppBView</code>. Except it really isn't and you shouldn't treat it as such or pretend that it is. </p> <p>After all, if a recipe calls for orange juice, then you don't take a lemon, paint it orange, juice it and call it orange juice. Do you?</p> <p>So what to do? Well, if all you want to do is send the <code>ID_FILE_PRINT</code> message, you don't even need a <code>CWnd</code> as such. You could just just do:</p> <pre><code>::SendMessage(hWnd, ID_FILE_PRINT, 0, 0); </code></pre> <p>Of course, that's <strong>also</strong> likely to be wrong. What you probably <strong>meant</strong> to do was this:</p> <pre><code>::SendMessage(hWnd, WM_COMMAND, ID_FILE_PRINT, 0); </code></pre> <p><strong>Update</strong>:</p> <p>Again, you <strong>CANNOT</strong> do what you are trying to do. Let's go step by step, shall we?</p> <pre><code>//Returns a CWnd even though the handle is to a valid CView CHFTAppBView* pView2 = (CHFTAppBView*) CHFTAppBView::FromHandle(hWnd); </code></pre> <p>Right. <code>CWnd::FromHandle</code> returns a pointer to a <code>CWnd</code>, not to anything else. It is <em>NOT</em> giving you back a pointer to your original <code>CHFTAppBView</code>. It's giving you a <strong>NEW</strong> <code>CWnd</code> which is attached to that same <code>HWND</code>. It is <strong>NOT VALID</strong> to cast that to a <code>CHFTAppBView</code> because this new <code>CWnd</code> is not a <code>CHFTAppBView</code>. </p> <pre><code>//Doesn't seem to do anything. Still returns a hWnd that the system recognizes as //a CWnd. That's what reports in the Watch window. CHFTAppBView* pView = reinterpret_cast&lt;CHFTAppBView*&gt;(CHFTAppBView::FromHandle(hWnd)); </code></pre> <p>Again, <code>CWnd::FromHandle</code> returns a pointer to a <em>new</em> <code>CWnd</code> which knows nothing about <code>CHFTAppBView</code>. You are telling the compiler "trust me, this pointer is to a <code>CHFTAppBView</code> object!" Except it is <em>NOT</em>. It is a pointer to a <code>CWnd</code> attached to a <code>HWND</code> that is a <code>CHFTAppBView</code>.</p> <pre><code>//Doesn't appear to do anything DYNAMIC_DOWNCAST( CHFTAppBView, pView ); </code></pre> <p>This <em>STILL</em> wouldn't do anything. First of all, <code>DYNAMIC_DOWNCAST</code> returns a pointer to <code>CHFTAppBView</code> so right there, you're calling the MFC RTTI functions but not doing anything with the result. But even if you did save the result, it wouldn't help. You would be trying to convert a generic <code>CWnd</code> into something it is not.</p> <p>I'll try to explain this one more time: When you create your view, MFC creates a <code>CHFTAppBView</code> object which is associated with the <code>HWND</code> of the view. When you call <code>CWnd::FromHandle</code> passing in the <code>HWND</code> of the view, MFC creates a <strong>NEW</strong> and distinct <code>CWnd</code> instance which points to that same <code>HWND</code> - that second <code>CWnd</code> is <strong>NOT</strong> <code>CHFTAppBView</code> and the <code>HWND</code> knows nothing about your MFC classes, views, documents or anything else.</p> <p>You are trying to take the <code>CWnd *</code> that <code>CWnd::FromHandle</code> returns and hammer it into a <code>CHFTAppBView *</code>. No matter how hard you try, this will not work. All you can ever get will be a <code>CWnd *</code> and nothing else.</p> <p>As a sidenote, you also cannot pass MFC objects from one thread to another, so passing the original <code>CHFTAppBView *</code> will cause weird issues to crop up, and may lead to hard to track errors.</p> <p><strong>Update 2:</strong></p> <p>You ask "<em>Why can't a CWnd object be cast to a window class that derrives from CWnd?</em>"</p> <p>Let's start from <code>CWnd::FromHandle</code> shall we?</p> <pre><code>CWnd* PASCAL CWnd::FromHandle(HWND hWnd) { CHandleMap* pMap = afxMapHWND(TRUE); //create map if not exist ASSERT(pMap != NULL); CWnd* pWnd = (CWnd*)pMap-&gt;FromHandle(hWnd); #ifndef _AFX_NO_OCC_SUPPORT pWnd-&gt;AttachControlSite(pMap); #endif ASSERT(pWnd == NULL || pWnd-&gt;m_hWnd == hWnd); return pWnd; } </code></pre> <p>This leads us to <code>CHandleMap::FromHandle</code>. The code for that is a bit complicated and posting it here won't help, so let's not clutter things up. But here is what the function does, conceptually:</p> <p>If a handle is found in the map, it returns it; otherwise, it creates a new <code>CWnd</code> and makes that <code>CWnd</code> point to the <code>HWND</code> you passed in. It then returns a pointer to that <code>CWnd</code> to you. But notice, this is <strong>ONLY</strong> a <code>CWnd</code>. Nothiong else. So you see, you cannot just convert that returned <code>CWnd</code> to something else - even if the something else is derived from a <code>CWnd</code> - because what you have is just a <code>CWnd</code> and nothing more.</p> <p>Let's say you have a wife. She is very beautiful and you love her very much. You carry a picture of her in your wallet. Now, when you meet someone and they ask if you are married, you take out your wallet and proudly show them her picture. The person to who you're talking do doesn't think that you are married to the picture. And you don't think that you can magically "convert" the picture into your wife. </p> <p>The situation here is somewhat similar. <code>CWnd::FromHandle</code> gives you a "picture" of sorts. It's good for showing around, but not good for much else. You are asking "why can't I transform the picture to my wife?" The answer is because that's not how pictures work.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload