473,287 Members | 1,899 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,287 software developers and data experts.

Using Metafiles

Hi everyone,

I need to draw some rft to the screen. And I found some code out there that
uses a Richedit control and sends it an EM_FORMATRANGE to do exactly that.

Now I need to add scaling to this code. What I'm trying to do is to have
the richedit control draw to a metafile and then I can set the ScaleTrasform
of the Graphics object and draw the metafile.

But everytime I call Metafile.GetHenhmetafile() it throws a "Parameter is
not valid" execption.

I haven't been able to find a solution to this problem anywhere.

public void Draw(Graphics graphics, RectangleF layoutArea, float
xFactor)
{
//Calculate the area to render.
SafeNativeMethods.RECT rectLayoutArea;
rectLayoutArea.Top = (int)(layoutArea.Top * anInch);
rectLayoutArea.Bottom = (int)(layoutArea.Bottom * anInch);
rectLayoutArea.Left = (int)(layoutArea.Left * anInch);
rectLayoutArea.Right = (int)(layoutArea.Right * anInch);

IntPtr hdc = graphics.GetHdc();

Metafile metafile = new Metafile(hdc, layoutArea);

//Release the device context handle obtained by a previous call
graphics.ReleaseHdc(hdc);

IntPtr hDCEMF = metafile.GetHenhmetafile(); <-------- I can't
get passed this line!

SafeNativeMethods.FORMATRANGE fmtRange;
fmtRange.chrg.cpMax = -1; //Indicate character from
to character to
fmtRange.chrg.cpMin = 0;
fmtRange.hdc = hDCEMF; //Use the same DC for
measuring and rendering
fmtRange.hdcTarget = hDCEMF; //Point at printer hDC
fmtRange.rc = rectLayoutArea; //Indicate the area on page
to print
fmtRange.rcPage = rectLayoutArea; //Indicate size of page

IntPtr wParam = IntPtr.Zero;
wParam = new IntPtr(1);

//Get the pointer to the FORMATRANGE structure in memory
IntPtr lParam = IntPtr.Zero;
lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
Marshal.StructureToPtr(fmtRange, lParam, false);

SafeNativeMethods.SendMessage(this.Handle,
SafeNativeMethods.EM_FORMATRANGE, wParam, lParam);

//Free the block of memory allocated
Marshal.FreeCoTaskMem(lParam);

graphics.ScaleTransform(xFactor, xFactor);

graphics.DrawImage(metafile, layoutArea.Location);
}
AliR.
Aug 12 '08 #1
5 6256
On Tue, 12 Aug 2008 08:50:36 -0700, AliR (VC++ MVP) <Al**@online.nospam>
wrote:
Hi everyone,

I need to draw some rft to the screen. And I found some code out there
that
uses a Richedit control and sends it an EM_FORMATRANGE to do exactly
that.

Now I need to add scaling to this code. What I'm trying to do is to have
the richedit control draw to a metafile and then I can set the
ScaleTrasform
of the Graphics object and draw the metafile.

But everytime I call Metafile.GetHenhmetafile() it throws a "Parameter is
not valid" execption.
Why not use Graphics.FromImage() to get a Graphics instance from the
Metafile, and then Graphics.GetHdc() to get the HDC to assign to
fmtRange.chrg.hdc?

By the way, the class "SafeNativeMethods" looks very much like code from
the .NET Framework itself. I don't know where you got that, but you may
want to be very careful to not be using code copied from .NET.
Microsoft's published the code, but I'm pretty sure the license is for
debugging purposes only, not for reuse within your own code.

Pete
Aug 12 '08 #2
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
Why not use Graphics.FromImage() to get a Graphics instance from the
Metafile, and then Graphics.GetHdc() to get the HDC to assign to
fmtRange.chrg.hdc?

By the way, the class "SafeNativeMethods" looks very much like code from
the .NET Framework itself. I don't know where you got that, but you may
want to be very careful to not be using code copied from .NET.
Microsoft's published the code, but I'm pretty sure the license is for
debugging purposes only, not for reuse within your own code.

Pete
I got the code from here http://www.andrewvos.com/?p=392
which is pretty much the same code as
http://support.microsoft.com/kb/812425/en-us
Which .Net code are you refering to? Am I reinventing the wheele? Is there
built-in code that does this already?

I don't really see how GraphicFromImage is going to help. Under native c++
code, I have to draw to a meta file and then I can use world transformations
to scale the text in a way that would not case detering and things like
that.

I tried your suggestion but it didn't draw anything.

public void Draw(Graphics graphics, RectangleF layoutArea, float
xFactor)
{
//Calculate the area to render.
SafeNativeMethods.RECT rectLayoutArea;
rectLayoutArea.Top = (int)(layoutArea.Top * anInch);
rectLayoutArea.Bottom = (int)(layoutArea.Bottom * anInch);
rectLayoutArea.Left = (int)(layoutArea.Left * anInch);
rectLayoutArea.Right = (int)(layoutArea.Right * anInch);

IntPtr hdc = graphics.GetHdc();

Metafile metafile = new Metafile(hdc, layoutArea);

Graphics metagraphic = Graphics.FromImage(metafile);
IntPtr hDCEMF = metagraphic.GetHdc();

SafeNativeMethods.FORMATRANGE fmtRange;
fmtRange.chrg.cpMax = -1; //Indicate character from
to character to
fmtRange.chrg.cpMin = 0;
fmtRange.hdc = hDCEMF; //Use the same DC for
measuring and rendering
fmtRange.hdcTarget = hDCEMF; //Point at printer hDC
fmtRange.rc = rectLayoutArea; //Indicate the area on page
to print
fmtRange.rcPage = rectLayoutArea; //Indicate size of page

IntPtr wParam = IntPtr.Zero;
wParam = new IntPtr(1);

//Get the pointer to the FORMATRANGE structure in memory
IntPtr lParam = IntPtr.Zero;
lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
Marshal.StructureToPtr(fmtRange, lParam, false);

SafeNativeMethods.SendMessage(this.Handle,
SafeNativeMethods.EM_FORMATRANGE, wParam, lParam);

//Free the block of memory allocated
Marshal.FreeCoTaskMem(lParam);

metagraphic.ReleaseHdc(hDCEMF);
//Release the device context handle obtained by a previous call
graphics.ReleaseHdc(hdc);

graphics.ScaleTransform(xFactor, xFactor);

graphics.DrawImage(metafile, layoutArea.Location);
}
Aug 12 '08 #3
"AliR (VC++ MVP)" <Al**@online.nospamwrote in message
news:iC******************@nlpi067.nbdc.sbc.com...
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
>Why not use Graphics.FromImage() to get a Graphics instance from the
Metafile, and then Graphics.GetHdc() to get the HDC to assign to
fmtRange.chrg.hdc?

By the way, the class "SafeNativeMethods" looks very much like code from
the .NET Framework itself. I don't know where you got that, but you may
want to be very careful to not be using code copied from .NET.
Microsoft's published the code, but I'm pretty sure the license is for
debugging purposes only, not for reuse within your own code.

Pete

I got the code from here http://www.andrewvos.com/?p=392
which is pretty much the same code as
http://support.microsoft.com/kb/812425/en-us
Which .Net code are you refering to? Am I reinventing the wheele? Is
there built-in code that does this already?

I don't really see how GraphicFromImage is going to help. Under native
c++ code, I have to draw to a meta file and then I can use world
transformations to scale the text in a way that would not case detering
and things like that.

I tried your suggestion but it didn't draw anything.

public void Draw(Graphics graphics, RectangleF layoutArea, float
xFactor)
{
//Calculate the area to render.
SafeNativeMethods.RECT rectLayoutArea;
rectLayoutArea.Top = (int)(layoutArea.Top * anInch);
rectLayoutArea.Bottom = (int)(layoutArea.Bottom * anInch);
rectLayoutArea.Left = (int)(layoutArea.Left * anInch);
rectLayoutArea.Right = (int)(layoutArea.Right * anInch);

IntPtr hdc = graphics.GetHdc();

Metafile metafile = new Metafile(hdc, layoutArea);

Graphics metagraphic = Graphics.FromImage(metafile);
IntPtr hDCEMF = metagraphic.GetHdc();

SafeNativeMethods.FORMATRANGE fmtRange;
fmtRange.chrg.cpMax = -1; //Indicate character from
to character to
fmtRange.chrg.cpMin = 0;
fmtRange.hdc = hDCEMF; //Use the same DC for
measuring and rendering
fmtRange.hdcTarget = hDCEMF; //Point at printer hDC
fmtRange.rc = rectLayoutArea; //Indicate the area on
page to print
fmtRange.rcPage = rectLayoutArea; //Indicate size of page

IntPtr wParam = IntPtr.Zero;
wParam = new IntPtr(1);

//Get the pointer to the FORMATRANGE structure in memory
IntPtr lParam = IntPtr.Zero;
lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
Marshal.StructureToPtr(fmtRange, lParam, false);

SafeNativeMethods.SendMessage(this.Handle,
SafeNativeMethods.EM_FORMATRANGE, wParam, lParam);

//Free the block of memory allocated
Marshal.FreeCoTaskMem(lParam);

metagraphic.ReleaseHdc(hDCEMF);
//Release the device context handle obtained by a previous call
graphics.ReleaseHdc(hdc);

graphics.ScaleTransform(xFactor, xFactor);

graphics.DrawImage(metafile, layoutArea.Location);
}

Here is the MFC version of this:
// setup rectangles for metafile fiddling
DC->DPtoHIMETRIC(&cTargetSize); // from MM_Text to MM_HIMETRIC
CRect cHiMetricRect(0,0,cTargetSize.cx,cTargetSize.cy);
CRect cTwipsRect(0,0,(TWIPS_INCH * cTargetSize.cx + HIMETRIC_INCH / 2) /
HIMETRIC_INCH,
(TWIPS_INCH * cTargetSize.cy + HIMETRIC_INCH / 2) / HIMETRIC_INCH);

// create the enhanced metafile
HDC hDCEMF = CreateEnhMetaFile(DC->m_hDC,NULL,cHiMetricRect,NULL);

// setup the format struct and do the RTF range formatting call
FORMATRANGE stFR;
stFR.hdcTarget = stFR.hdc = hDCEMF; // render to the memory helper EMF
stFR.rcPage = stFR.rc = cTwipsRect; // using this rectangle (in twips)
stFR.chrg.cpMin = 0; // and render all of the text
stFR.chrg.cpMax = -1;
pCtrl->SendMessage(EM_FORMATRANGE,TRUE,(LPARAM) &stFR);
pCtrl->SendMessage(EM_FORMATRANGE,TRUE,NULL); // this call clears the cache

// drawing into the metafile is done, get ourselves an handle to it (used
for the replay)
HENHMETAFILE hEMF = CloseEnhMetaFile(hDCEMF);

// calculate the automagic fudge factors by getting the device metrics
int nHorzSize = DC->GetDeviceCaps(HORZSIZE ); // width in millimeters
int nVertSize = DC->GetDeviceCaps(VERTSIZE ); // height in millimeters
int nHorzRes = DC->GetDeviceCaps(HORZRES ); // width in pixels
int nVertRes = DC->GetDeviceCaps(VERTRES ); // height in pixels
int nLogPixelsX = DC->GetDeviceCaps(LOGPIXELSX); // # of pixels per inch
horizontally
int nLogPixelsY = DC->GetDeviceCaps(LOGPIXELSY); // # of pixels per inch
vertically

float fHorzSizeInches = nHorzSize / 25.4f;
float fVertSizeInches = nVertSize / 25.4f;
float fHorzFudgeFactor = (nHorzRes / fHorzSizeInches) / nLogPixelsX; //
divide expected DPI with actual DPI
float fVertFudgeFactor = (nVertRes / fVertSizeInches) / nLogPixelsY; //

// do the world transforms, first apply the scale and fudge factors
XFORM stX;
ZeroMemory(&stX,sizeof(stX));
stX.eM11 = fHorzFudgeFactor * (m_XFactor);
stX.eM22 = fVertFudgeFactor * (m_XFactor);
SetWorldTransform(DC->m_hDC,&stX);

long Top = WinRect.top;
long Left = WinRect.left;
WinRect.OffsetRect(-Left,-Top);
WinRect.OffsetRect((int)(Left/fHorzFudgeFactor),int(Top/fVertFudgeFactor));

DC->PlayMetaFile(hEMF,&WinRect);

// that's it, kiss the metafile goodbye
DeleteEnhMetaFile(hEMF);
Aug 12 '08 #4
On Tue, 12 Aug 2008 11:27:29 -0700, AliR (VC++ MVP) <Al**@online.nospam>
wrote:
I got the code from here http://www.andrewvos.com/?p=392
which is pretty much the same code as
http://support.microsoft.com/kb/812425/en-us
Which .Net code are you refering to? Am I reinventing the wheele? Is
there
built-in code that does this already?
That I know of, no. I was simply commenting on the class
"SafeNativeMethods", because that's the exact name used in the .NET
Framework's implementation. Could be that the original source lifted it
from the .NET source code, or just the name.

Personally, it doesn't concern me one way or the other. It's just that
someone using that code should be careful if they are at all concerned
about running afoul of Microsoft's legal department (which, while not as
rabid as those found in other corporations, do still need to justify their
existence).
I don't really see how GraphicFromImage is going to help.
The Graphics instance you get from that wraps the Metafile itself, so any
DC you get from that Graphics instance is for the Metafile.

In other words, the HDC that you get from the Graphics instance returned
by that method returns exactly the thing you need to assign to the
FORMATRANGE.hdc field.

I don't know why the call to Metafile.GetHenhmetafile() doesn't work,
other than the fact that I personally have had trouble with the .NET
Metafile implementation in the past (in other words, things that you'd
think would work based on how the unmanaged version works, wind up not
working). But I do know that you can get an HDC that draws into the
Metafile by using Graphics.FromImage() and the Graphics.GetHdc(). I'm
pretty sure I've done that before and had it work (for sure it works with
Bitmaps, and I'm pretty sure I've used it with Metafiles too).
Under native c++
code, I have to draw to a meta file and then I can use world
transformations
to scale the text in a way that would not case detering and things like
that.

I tried your suggestion but it didn't draw anything.
Well, it at least didn't cause an error, right?

I can't say exactly what's wrong with the code you're using. But I
suspect you're closer to a solution now than you were before. :)

You'll probably have to break the problem down into smaller parts and see
what's not working as expected. The code you're using is almost, but not
exactly, like the MSDN code, so one place to start would be to start with
_exactly_ the code in the MSDN sample and see if you can get that to work.

You should also check to see whether you're able to create a Metafile via
more conventional means that does what you want, to double-check that your
Metafile-specific code is valid.

And of course, I hope this is a silly question, but you are in fact
putting that code in a control that inherits RichTextBox, right?

Pete
Aug 12 '08 #5
I think I got it: (thank you Peter for your help)

public void Draw(Graphics graphics, RectangleF layoutArea, float
xFactor)
{
//Calculate the area to render.
SafeNativeMethods.RECT rectLayoutArea;
rectLayoutArea.Top = (int)(0 * anInch);
rectLayoutArea.Bottom = (int)(layoutArea.Bottom * anInch);
rectLayoutArea.Left = (int)(0 * anInch);
rectLayoutArea.Right = (int)(layoutArea.Right * anInch);
Bitmap Bmp = new Bitmap((int)layoutArea.Width,
(int)layoutArea.Height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(Bmp);
IntPtr hdc = g.GetHdc();

//create a metafile, convert the size to himetrics
Metafile metafile = new Metafile(hdc, new
RectangleF(0,0,layoutArea.Width*26,layoutArea.Heig ht*26));

g.ReleaseHdc(hdc);
g.Dispose();

g = Graphics.FromImage(metafile);
IntPtr hDCEMF = g.GetHdc();

SafeNativeMethods.FORMATRANGE fmtRange;
fmtRange.chrg.cpMax = -1; //Indicate character from
to character to
fmtRange.chrg.cpMin = 0;
fmtRange.hdc = hDCEMF; //Use the same DC for
measuring and rendering
fmtRange.hdcTarget = hDCEMF; //Point at printer hDC
fmtRange.rc = rectLayoutArea; //Indicate the area on page
to print
fmtRange.rcPage = rectLayoutArea; //Indicate size of page

IntPtr wParam = IntPtr.Zero;
wParam = new IntPtr(1);

//Get the pointer to the FORMATRANGE structure in memory
IntPtr lParam = IntPtr.Zero;
lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
Marshal.StructureToPtr(fmtRange, lParam, false);

SafeNativeMethods.SendMessage(this.Handle,
SafeNativeMethods.EM_FORMATRANGE, wParam, lParam);

//Free the block of memory allocated
Marshal.FreeCoTaskMem(lParam);

//Release the device context handle obtained by a previous call
g.ReleaseHdc(hDCEMF);
g.Dispose();

graphics.ScaleTransform(xFactor, xFactor);
graphics.DrawImage(metafile, layoutArea.Location);
}

AliR.

Aug 12 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Barry | last post by:
Thanks for any help provided. How can I access enhancedmetafile format images in the Windows clipboard? The images appear when you use the clipbook viewer in the "Clipboard" not the "Local...
2
by: rawCoder | last post by:
Hi All, I have a *.cer file, a public key of some one and I want to encrypt some thing using this public key. Can someone point me to a sample code for Encrypting some file using...
1
by: Mike | last post by:
When trying to compile (using Visual Web Developer 2005 Express Beta; frameworkv2.0.50215 ) the source code below I get errors (listed below due to the use of ICallBackEventHandler. Ultimately I...
10
by: Christopher Benson-Manica | last post by:
Why can't I use a class destructor in a using declaration: using MyClass::~MyClass; ? -- Christopher Benson-Manica | I *should* know what I'm talking about - if I ataru(at)cyberspace.org ...
17
by: beliavsky | last post by:
Many of my C++ programs have the line using namespace std; but the "Accelerated C++" book of Koenig and Moo has many examples where the library names are included one at a time, for example ...
15
by: Peter Duniho | last post by:
I'm trying to use .NET and C# to draw a metafile copied to the clipboard by another application (Word 2003 in this case, but it shouldn't matter). I naively thought that I'd be able to use the...
2
by: rejidasan | last post by:
Hello All, I have a MFC Dialog based application. I am not using GDI or GDI+ libraries. I need to load PNG and JPEG images in this Dialog Based application. Can you suggest me how to to do...
3
by: JDeats | last post by:
I have some .NET 1.1 code that utilizes this technique for encrypting and decrypting a file. http://support.microsoft.com/kb/307010 In .NET 2.0 this approach is not fully supported (a .NET 2.0...
0
by: Christian Nein | last post by:
Hi, does anybody know a component or library that deals with metafiles? In particular I am searching for a way to build 1 Metafile from many metafiles by assembling them together. With bitmaps...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.