Solved

Using HDC.FromHandle and CDC::GetSafeHdc

Posted on 1998-08-31
8
1,538 Views
Last Modified: 2013-11-19
OK, I'm trying to pass a CDC* to my ActiveX control by passing the HDC of the control and using it to display.  

Now to test my problem, I tested a few functions and tried to see if the CDC was really my new CDC or not.

TRACE1( "Map Mode: %d\n",  pDC->GetMapMode( ));

HDC hDC = pDC->GetSafeHdc( );
CDC* pTestDC = CDC::FromHandle( hDC );

TRACE1( "Map Mode: %d\n",  pTestDC->GetMapMode( ));

Hmmm! The mapping modes are now different! When printing, it went from MM_TEXT to MM_ANISOTROPIC.

SOOO... the way that I'm converting it doesn't work.  So how do I do it?

HDC hDC = pDC->GetSafeHdc( );
CDC pTestDC;
pTestDC.Attach( hDC );

Doesn't seem to work either.  Anyone?

Phillip

0
Comment
Question by:psdavis
  • 4
  • 2
  • 2
8 Comments
 
LVL 2

Expert Comment

by:milenvk
ID: 1321511
What about using SaveDC and RestoreDC? Right in your code this will look like:

TRACE1( "Map Mode: %d\n",  pDC->GetMapMode( ));

HDC hDC = pDC->GetSafeHdc( );
int nSavedDC = SaveDC(hDC);
CDC* pTestDC = CDC::FromHandle( hDC );
RestoreDC(pTestDC->m_hDC, nSavedDC);

TRACE1( "Map Mode: %d\n",  pTestDC->GetMapMode( ));

This is not as elegant but at least solves the problem :-) You just have to pass to your control the value returned by SaveDC along with the HDC itself.
0
 
LVL 7

Author Comment

by:psdavis
ID: 1321512
I'm already around the problem, so I'm not looking for a kludge.  I just really want to know how you're supposed to do it in the first place, but thanks.

0
 
LVL 2

Expert Comment

by:milenvk
ID: 1321513
I looked the the Attach version of your test.
I looked at the code of CDC::Attach() and it seems that there shouldn't be a different result. Why don't you debug the functions deeper in the MFC code. Check if both HDCs in the first and second trace are the same (they should be). If they are not try to spot where and how the HDC gets changed (frankly, I don't see how this is possible looking at the MFC code). And finally if they are equal try to find out why the map mode changed during the transition.
0
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 
LVL 8

Accepted Solution

by:
Answers2000 earned 70 total points
ID: 1321514
I'm a little unclear on what's in the app and what's in the ActiveX. So if I my assumptions are incorrect, it might help if you could make that a bit clearer.

One general point, then a stab at the answer

GENERAL POINT

Aside from anything else though, you need to look at what you're trying to do.  

1. An MFC app and an MFC ActiveX component are using different copies of MFC, that means you can not share MFC objects between them.  So in your case you can't point a CDC *, but will have to pass an HDC and reconstruct in the ActiveX control.  You seem to have realized this (?) as I suspect you pass hDC into the ActiveX control.
HDC hDC = pDC->GetSafeHdc( );
    ^
    |
    |
  You're passing this ?

2. If you really want to share MFC objects between an MFC app and a DLL, you need to make the DLL an MFC extension DLL.  That's an aside though.


THE ANSWER ?

1. Now putting all that aside you need to remember that the CDC object encapsulates two HDCs (m_hDC and m_hAttribDC - see the help topic on the CDC Class Overview).  

2. MFC gets/sets all attributes thru m_hAttribDC and does drawing thru m_hDC.  Normally m_hAttribDC and m_hDC contain the same HDC - but NOT always (for example a metafile).

3. Now looking at your code, both variants do
HDC hDC = pDC->GetSafeHdc( );
Which gets m_hDC from the CDC.  
However any mapping modes etc. are set thru m_hAttribDC which may be a different HDC.  Reconstructing (both methods you do are okay) you loose the m_hAttribDC value and its settings.

The solution then is to
EITHER
(i) pass both HDC's into the ActiveX control (and reconstruct the CDC from both of them) - adding a SetAttribDC on pTestDC should do this for you
OR
(ii) Set the attributes on the m_hDC to match those on m_hAttribDC (if they really are different HDCs) before passing thru in to the ActiveX
OR
(iii) Switch to MFC Extension DLL architecture and just share the CDC objects between the main app and the DLL.

0
 
LVL 7

Author Comment

by:psdavis
ID: 1321515
I'll look into both comments.  Thanks guys.

To clarify, I'm eliminating worrying about the ActiveX passing until I figure out how to do it in just the code snipplet.  Then I'll worry.

HDC hDC = pDC->GetSafeHdc( );

Yes, I was passing the hDC.  To get around it, I'm currently passing the pDC as a long* to my ActiveX control.  Once it gets there, I'm casting it back to a CDC*.  Actually works great.  I'm doing it with the tooltips as well.  No problems.

Phillip

0
 
LVL 7

Author Comment

by:psdavis
ID: 1321516
Answers2000,

So this is the final solution for this code snipplet?

// To get the two HDC

HDC hDC       = pDC->m_hDC;
HDC hAttribDC = pDC->m_hAttribDC;

// To convert it back

CDC* pTestDC = CDC::FromHandle( hDC );
pTestDC->SetAttribDC( hAttribDC );

// or alternatively

CDC pTestDC;
pTestDC.Attach( hDC );
pTestDC.SetAttribDC( hAttribDC );

// Correct?

Phillip

0
 
LVL 8

Expert Comment

by:Answers2000
ID: 1321517
Yes I believe so Phillip,

I've been reading the CDC sources and it looks right to me, though I have to say I haven't actually tried a test project.

Let me know how you get on

Incidentally I believe I've figured out milenvk's work round works.  It's because the SaveDC get's the attribute DC's attributes saved in the main app, and the restore puts the attributes back in the ActiveX's attribute DC (which may not be the same attribute DC as in the main app).

The only funny thing is (as usual) the MFC doc's are less than 100% clear when the attribute DC won't be the same as the hDC.

As far as I can tell your final code should work in all cases though.
0
 
LVL 7

Author Comment

by:psdavis
ID: 1321518
> Incidentally I believe I've figured out milenvk's work round works

I agree completely, but it was more of a intellectual question than a solution question.

Thanks,
Phillip
0

Featured Post

Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Creating Labels and Frequency list style reports in SAS code 9 98
format the code in java 6 95
Smart Camera scanning and reading information 3 106
Line meaning 9 86
Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…

803 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