1. Trang chủ
  2. » Công Nghệ Thông Tin

programming windows phần 9 ppsx

128 267 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Programming Windows Phần 9
Trường học University of Programming
Chuyên ngành Computer Science
Thể loại Bài tập
Năm xuất bản 2025
Thành phố Hanoi
Định dạng
Số trang 128
Dung lượng 410,53 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

EMFVIEW MENU DISCARDABLE BEGIN POPUP "&File" BEGIN MENUITEM "&Open\tCtrl+O", IDM_FILE_OPEN MENUITEM "Save &As...", IDM_FILE_SAVE_AS MENUITEM "Cu&t\tCtrl+X", IDM_EDIT_CUT MENUITEM "

Trang 1

// Show the File Save dialog box

// Save the EMF to disk file

SetCursor (LoadCursor (NULL, IDC_WAIT)) ;

MessageBox (hwnd, TEXT ("Cannot save metafile"),

szAppName, MB_ICONEXCLAMATION | MB_OK) ;

return 0 ;

case IDM_FILE_PRINT:

// Show the Print dialog box and get printer DC

printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ;

MessageBox (hwnd, TEXT ("Cannot obtain printer DC"),

szAppName, MB_ICONEXCLAMATION | MB_OK) ;

// Play the EMF to the printer

SetCursor (LoadCursor (NULL, IDC_WAIT)) ;

Trang 2

ShowCursor (FALSE) ;

SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

DeleteDC (hdcPrn) ;

if (!bSuccess)

MessageBox (hwnd, TEXT ("Could not print metafile"),

szAppName, MB_ICONEXCLAMATION | MB_OK) ;

return 0 ;

case IDM_FILE_PROPERTIES:

if (!hemf)

return 0 ;

iLength = GetEnhMetaFileDescription (hemf, 0, NULL) ;

pBuffer = malloc ((iLength + 256) * sizeof (TCHAR)) ;

GetEnhMetaFileHeader (hemf, sizeof (ENHMETAHEADER), &header) ; // Format header file information

TEXT ("Resolution = (%i, %i) pixels")

TEXT (" = (%i, %i) mms\n"),

header.szlDevice.cx, header.szlDevice.cy,

header.szlMillimeters.cx,

header.szlMillimeters.cy) ;

i += wsprintf (pBuffer + i,

TEXT ("Size = %i, Records = %i, ")

TEXT ("Handles = %i, Palette entries = %i\n"), header.nBytes, header.nRecords,

header.nHandles, header.nPalEntries) ;

// Include the metafile description, if present

if (iLength)

{

i += wsprintf (pBuffer + i, TEXT ("Description = ")) ;

GetEnhMetaFileDescription (hemf, iLength, pBuffer + i) ; pBuffer [lstrlen (pBuffer)] = `\t' ;

// Transfer metafile copy to the clipboard

hemfCopy = CopyEnhMetaFile (hemf, NULL) ;

Trang 3

SetClipboardData (CF_ENHMETAFILE, hemfCopy) ;

hemf = CopyEnhMetaFile (hemfCopy, NULL) ;

InvalidateRect (hwnd, NULL, TRUE) ;

return 0 ;

case IDM_APP_ABOUT:

MessageBox (hwnd, TEXT ("Enhanced Metafile Viewer\n") TEXT ("(c) Charles Petzold, 1998"), szAppName, MB_OK) ;

Trang 5

EMFVIEW MENU DISCARDABLE

BEGIN

POPUP "&File"

BEGIN

MENUITEM "&Open\tCtrl+O", IDM_FILE_OPEN

MENUITEM "Save &As ", IDM_FILE_SAVE_AS

MENUITEM "Cu&t\tCtrl+X", IDM_EDIT_CUT

MENUITEM "&Copy\tCtrl+C", IDM_EDIT_COPY

MENUITEM "&Paste\tCtrl+V", IDM_EDIT_PASTE

MENUITEM "&Delete\tDel", IDM_EDIT_DELETE

EMFVIEW ACCELERATORS DISCARDABLE

BEGIN

"C", IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT

"O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT

"P", IDM_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT

"V", IDM_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT

VK_DELETE, IDM_EDIT_DELETE, VIRTKEY, NOINVERT

"X", IDM_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT

END

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 6

RESOURCE.H (excerpts)

// Microsoft Developer Studio generated include file.

// Used by EmfView.rc

#define IDM_FILE_OPEN 40001

#define IDM_FILE_SAVE_AS 40002

#define IDM_FILE_PRINT 40003

#define IDM_FILE_PROPERTIES 40004

#define IDM_APP_EXIT 40005

#define IDM_EDIT_CUT 40006

#define IDM_EDIT_COPY 40007

#define IDM_EDIT_PASTE 40008

#define IDM_EDIT_DELETE 40009

#define IDM_APP_ABOUT 40010

EMFVIEW also has complete palette logic, just in case a palette has been encoded in the metafile (The way it gets

in there is by a call to SelectPalette.) The program extracts the palette in its CreatePaletteFromMetaFile function,

which is called when it displays a metafile during WM_PAINT and also while processing the

WM_QUERYNEWPALETTE and WM_PALETTECHANGED messages

In response to a Print command from the menu, EMFVIEW displays the common printer dialog box and then obtains the dimensions of the printable area of the page The metafile is stretched to fill that whole area EMFVIEW displays a metafile in its window similarly

The Properties item from the File menu causes EMFVIEW to display a message box containing information from the metafile header

If you print the EMF2.EMF metafile image created earlier in this chapter, you may find that the lines are very thin on high-resolution printers, perhaps nearly invisible Vector images should really have wider pens (for example, 1-point wide) for printing The ruler image shown later in this chapter does that

Displaying Accurate Metafile Images

The great thing about metafile images is that they can be stretched to any size and still maintain reasonable fidelity This is because a metafile normally consists of a series of vector graphics primitives, such as lines, filled areas, and outline fonts Enlarging or compressing the image simply involves scaling all the coordinate points that define these primitives Bitmaps, on the other hand, can lose vital information when compression results in dropping entire rows and columns of pixels

Of course, metafile compression in real life is not entirely flawless either We live with graphical output devices that have a finite pixel size A metafile image consisting of lots of lines could start to look like an indecipherable blob when compressed in size Also, area-filling patterns and color dithering start to look odd at small sizes And, if the metafile contains embedded bitmaps or old-fashioned raster fonts, these too can pose familiar problems

For the most part, though, metafiles are freely scaleable This is most useful when dropping a metafile into a word processing or desktop publishing document Generally, when you select a metafile image in such an application, you'll

be presented with a bounding rectangle that you can grab with the mouse and scale to any size The image will also have the same relative size when rendered on a printer

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 7

Sometimes, however, arbitrarily scaling a metafile is not such a hot idea An example: Suppose you have a bankingsystem that stores facsimiles of account-holders' signatures as a series of polylines stored in a metafile Widening orheightening this metafile would make the signature look different At the very least, you should keep the image'saspect ratio constant

In the sample programs shown previously, we've based the bounding rectangle in the PlayEnhMetaFile call on the

size of the client area Thus, as you resize the program's window, you effectively resize the image This is conceptuallysimilar to resizing a metafile image within a word-processing document

Accurately displaying a metafile image either in specific metrical sizes or with a proper aspect ratio requires using sizeinformation in the metafile header and setting the rectangle structure accordingly

The sample programs in the remainder of this chapter will use a shell program called EMF.C that includes printinglogic, a resource script named EMF.RC, and a RESOURCE.H header file Figure 18-15 shows these files alongwith EMF8.C, a program that uses these files to display a 6-inch ruler

Figure 18-15 The EMF8 program

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 8

TCHAR szClass [] = TEXT ("EMF8") ;

TCHAR szTitle [] = TEXT ("EMF8: Enhanced Metafile Demo #8") ;

void DrawRuler (HDC hdc, int cx, int cy)

// Black pen with 1-point width

SelectObject (hdc, CreatePen (PS_SOLID, cx / 72 / 6, 0)) ;

// Rectangle surrounding entire pen (with adjustment)

Rectangle (hdc, iAdj, iAdj, cx + iAdj + 1, cy + iAdj + 1) ;

else iHeight = cy / 12 ; // sixteenths MoveToEx (hdc, i * cx / 96, cy, NULL) ;

LineTo (hdc, i * cx / 96, cy - iHeight) ;

}

// Create logical font

FillMemory (&lf, sizeof (lf), 0) ;

lf.lfHeight = cy / 2 ;

lstrcpy (lf.lfFaceName, TEXT ("Times New Roman")) ;

SelectObject (hdc, CreateFontIndirect (&lf)) ;

SetTextAlign (hdc, TA_BOTTOM | TA_CENTER) ;

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 9

void CreateRoutine (HWND hwnd)

{

HDC hdcEMF ;

HENHMETAFILE hemf ;

int cxMms, cyMms, cxPix, cyPix, xDpi, yDpi ;

hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf8.emf"), NULL,

TEXT ("EMF8\0EMF Demo #8\0")) ;

if (hdcEMF == NULL)

return ;

cxMms = GetDeviceCaps (hdcEMF, HORZSIZE) ;

cyMms = GetDeviceCaps (hdcEMF, VERTSIZE) ;

cxPix = GetDeviceCaps (hdcEMF, HORZRES) ;

cyPix = GetDeviceCaps (hdcEMF, VERTRES) ;

xDpi = cxPix * 254 / cxMms / 10 ;

yDpi = cyPix * 254 / cyMms / 10 ;

DrawRuler (hdcEMF, 6 * xDpi, yDpi) ;

hemf = CloseEnhMetaFile (hdcEMF) ;

hemf = GetEnhMetaFile (TEXT ("emf8.emf")) ;

GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ;

cxImage = emh.rclBounds.right - emh.rclBounds.left ;

cyImage = emh.rclBounds.bottom - emh.rclBounds.top ;

rect.left = (cxArea - cxImage) / 2 ;

rect.right = (cxArea + cxImage) / 2 ;

rect.top = (cyArea - cyImage) / 2 ;

rect.bottom = (cyArea + cyImage) / 2 ;

PlayEnhMetaFile (hdc, hemf, &rect) ;

DeleteEnhMetaFile (hemf) ;

}

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 10

extern void CreateRoutine (HWND) ;

extern void PaintRoutine (HWND, HDC, int, int) ;

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

HANDLE hInst ;

extern TCHAR szClass [] ;

extern TCHAR szTitle [] ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 11

BOOL PrintRoutine (HWND hwnd)

{

static DOCINFO di ;

static PRINTDLG printdlg = { sizeof (PRINTDLG) } ;

static TCHAR szMessage [32] ;

BOOL bSuccess = FALSE ;

HDC hdcPrn ;

int cxPage, cyPage ;

printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ;

if (!PrintDlg (&printdlg))

return TRUE ;

if (NULL == (hdcPrn = printdlg.hDC))

return FALSE ;

cxPage = GetDeviceCaps (hdcPrn, HORZRES) ;

cyPage = GetDeviceCaps (hdcPrn, VERTRES) ;

lstrcpy (szMessage, szClass) ;

lstrcat (szMessage, TEXT (": Printing")) ;

di.cbSize = sizeof (DOCINFO) ;

Trang 12

cxClient = LOWORD (lParam) ;

cyClient = HIWORD (lParam) ;

Trang 13

Because modern printers often have a much higher resolution than video displays, the ability to print a metafile is animportant tool for testing our ability to render an image in a specific size The EMF8 program creates a metafile imagethat makes most sense when displayed in a specific size The image is that of a ruler 6 inches wide by 1 inch high,complete with tick marks every 16th inch and the numbers 1 through 5 in a TrueType font.

To draw a 6-inch ruler, we need to know something about device resolution The CreateRoutine function in

EMF8.C begins by creating a metafile and calling GetDeviceCaps four times using the device context handle

returned from CreateEnhMetaFile These calls obtain the width and height of the display surface in both millimeters

and pixels

This may sound a bit odd The metafile device context is usually seen as a storage medium for GDI drawing

commands It's not a real device like a video display or a printer, so how can it have a width and height?

Well, as you may recall, the first argument to CreateEnhMetaFile is known as the "reference device context." GDI

uses this to establish device characteristics for the metafile If the argument is set to NULL (as in EMF8), GDI uses

the video display as the reference device context Thus, when EMF8 calls GetDeviceCaps using the metafile device

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 14

context, it actually obtains information about the video display

EMF8.C calculates a resolution in dots per inch by dividing the pixel dimension by the millimeter dimension andmultiplying by 25.4, the number of millimeters in an inch

Even though we've taken great care to draw this metafile ruler in its correct size, the work is not yet done When it

comes time to render the image, the PlayEnhMetaFile function will display it stretched to the rectangle passed as its

last argument This rectangle must be set to the size of the ruler

For this reason, the PaintRoutine function in EMF8 calls the GetEnhMetaFileHeader function to obtain the header information in the metafile The rclBounds field of the ENHMETAHEADER structure indicates the bounding

rectangle of the metafile image in pixels The program uses this information to center the ruler in the client area, asshown in Figure 18-16

Figure 18-16 The EMF8 display

Keep in mind that if you hold a ruler up to the screen, you probably won't match exactly The video display onlyapproximates actual metrics, as I discussed in Chapter 5

This technique appears to have worked, but now try printing the image Oops! If you have a 300-dpi laser printer,the ruler will be about 11/3 inches wide That's because we've used a pixel dimension based on the video display.Although you may think the little printed ruler looks kind of cute, it's not what we want Let's try again

The ENHMETAHEADER structure contains two rectangle structures that describe the size of the image The first,

which EMF8 uses, is the rclBounds field This gives the size of the image in pixels The second is the rclFrame field,

which gives the size of the image in units of 0.01 millimeters The relationship between these two fields is governed bythe reference device context originally used when creating the metafile, in this case the video display (The metafile

header also contains two fields named szlDevice and szlMillimeters, which are SIZEL structures that indicate the size of the reference device in pixels and millimeters, the same information available from GetDeviceCaps.)

The information about the millimeter dimensions of the image is put to use by EMF9, shown in Figure 18-17

Figure 18-17 The EMF9 program

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 15

TCHAR szClass [] = TEXT ("EMF9") ;

TCHAR szTitle [] = TEXT ("EMF9: Enhanced Metafile Demo #9") ;

cyMms = GetDeviceCaps (hdc, VERTSIZE) ;

cxPix = GetDeviceCaps (hdc, HORZRES) ;

cyPix = GetDeviceCaps (hdc, VERTRES) ;

hemf = GetEnhMetaFile (TEXT (" \\emf8\\emf8.emf")) ;

GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ;

cxImage = emh.rclFrame.right - emh.rclFrame.left ;

cyImage = emh.rclFrame.bottom - emh.rclFrame.top ;

cxImage = cxImage * cxPix / cxMms / 100 ;

cyImage = cyImage * cyPix / cyMms / 100 ;

rect.left = (cxArea - cxImage) / 2 ;

rect.right = (cxArea + cxImage) / 2 ;

rect.top = (cyArea - cyImage) / 2 ;

rect.bottom = (cyArea + cyImage) / 2 ;

PlayEnhMetaFile (hdc, hemf, &rect) ;

DeleteEnhMetaFile (hemf) ;

}

EMF9 uses the metafile created by EMF8, so be sure to run EMF8 before running this program

The PaintRoutine function in EMF9 begins by calling GetDeviceCaps four times using the destination device context As in the CreateRoutine function in EMF8, these calls provide information about the resolution of the device After getting the metafile handle, it obtains the header structure and uses the rclFrame field to calculate the

size of the metafile image in units of 0.01 millimeters That's the first step

The function then converts this dimension to pixels by multiplying by the pixel dimension of the output device, dividing

by the millimeter dimension, and then dividing by 100 to account for the metrical dimension in 0.01 millimeters The

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 16

PaintRoutine function now has the dimensions of the ruler in pixels but not specific to the video display This is a

pixel dimension appropriate for the destination device From there on, it's easy to center the image

As far as the screen goes, the EMF9 display looks the same as the EMF8 display But if you print the ruler fromEMF9, you'll see something that looks much more normal a ruler 6 inches wide by 1 inch high

Scaling and Aspect Ratios

There may be times when you want to use the ruler metafile created by EMF8 but without necessarily displaying the6-inch image Still, it might be nice to maintain the correct 6-to-1 aspect ratio of the image As I mentioned before,using a bounding box to size a metafile in a word-processing program (or whatever) may be convenient, but it couldresult in certain undesirable distortions In such applications, users should be given an option to keep the originalaspect ratio regardless of how the bounding box is sized That is, the bounding box selected by the user would not be

used directly to define the rectangle structure passed to the PlayEnhMetaFile The rectangle structure passed to that

function would be only part of the bounding box

Let's examine how to do this in the EMF10 program shown in Figure 18-18

Figure 18-18 The EMF10 program

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 17

TCHAR szClass [] = TEXT ("EMF10") ;

TCHAR szTitle [] = TEXT ("EMF10: Enhanced Metafile Demo #10") ;

cyMms = GetDeviceCaps (hdc, VERTSIZE) ;

cxPix = GetDeviceCaps (hdc, HORZRES) ;

cyPix = GetDeviceCaps (hdc, VERTRES) ;

hemf = GetEnhMetaFile (TEXT (" \\emf8\\emf8.emf")) ;

GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ;

cxImage = emh.rclFrame.right - emh.rclFrame.left ;

cyImage = emh.rclFrame.bottom - emh.rclFrame.top ;

cxImage = cxImage * cxPix / cxMms / 100 ;

cyImage = cyImage * cyPix / cyMms / 100 ;

fScale = min ((float) cxArea / cxImage, (float) cyArea / cyImage) ;

cxImage = (int) (fScale * cxImage) ;

cyImage = (int) (fScale * cyImage) ;

rect.left = (cxArea - cxImage) / 2 ;

rect.right = (cxArea + cxImage) / 2 ;

rect.top = (cyArea - cyImage) / 2 ;

rect.bottom = (cyArea + cyImage) / 2 ;

PlayEnhMetaFile (hdc, hemf, &rect) ;

DeleteEnhMetaFile (hemf) ;

}

EMF10 stretches the ruler image to fit the client area (or the printable area of the printer page) but without otherwisedistorting it Usually you'll see the ruler stretching the full width of the client area but centered between the top andbottom If you make the window somewhat stout, the ruler will be as tall as the client area but centered horizontally.There are probably numerous ways of calculating the proper display rectangle, but I decided to build upon the code

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 18

in EMF9 The PaintRoutine function in EMF10.C begins like EMF9.C, by calculating the pixel size of the

6-inch-wide image appropriate for the destination device context

The program then calculates a floating point value, named fScale, that is the minimum of the ratio of the width of the

client area to the width of the image, and the ratio of the height of the client area to the height of the image This factor

is then used to increase the pixel dimensions of the image before the bounding rectangle is calculated

Mapping Modes in Metafiles

We've been drawing a ruler that displays inches, and we've also been dealing with dimensions in units of millimeters.Such jobs might seem like good candidates for using the various mapping modes provided under GDI Yet I'veinsisted on using pixels and doing all the necessary calculations "manually." Why is that?

The simple answer is that the use of mapping modes in connection with metafiles can be quite confusing But let's try

it out to see

When you call SetMapMode using a metafile device context, the function is encoded in the metafile just like any other

GDI function This is demonstrated in the EMF11 program shown in Figure 18-19

Figure 18-19 The EMF11 program

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 19

TCHAR szClass [] = TEXT ("EMF11") ;

TCHAR szTitle [] = TEXT ("EMF11: Enhanced Metafile Demo #11") ;

void DrawRuler (HDC hdc, int cx, int cy)

{

int i, iHeight ;

LOGFONT lf ;

TCHAR ch ;

// Black pen with 1-point width

SelectObject (hdc, CreatePen (PS_SOLID, cx / 72 / 6, 0)) ;

// Rectangle surrounding entire pen (with adjustment)

if (GetVersion () & 0x80000000) // Windows 98

else iHeight = cy / 12 ; // sixteenths MoveToEx (hdc, i * cx / 96, 0, NULL) ;

LineTo (hdc, i * cx / 96, iHeight) ;

}

// Create logical font

FillMemory (&lf, sizeof (lf), 0) ;

lf.lfHeight = cy / 2 ;

lstrcpy (lf.lfFaceName, TEXT ("Times New Roman")) ;

SelectObject (hdc, CreateFontIndirect (&lf)) ;

SetTextAlign (hdc, TA_BOTTOM | TA_CENTER) ;

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 20

hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf11.emf"), NULL,

TEXT ("EMF11\0EMF Demo #11\0")) ;

SetMapMode (hdcEMF, MM_LOENGLISH) ;

cyMms = GetDeviceCaps (hdc, VERTSIZE) ;

cxPix = GetDeviceCaps (hdc, HORZRES) ;

cyPix = GetDeviceCaps (hdc, VERTRES) ;

cxImage = emh.rclFrame.right - emh.rclFrame.left ;

cyImage = emh.rclFrame.bottom - emh.rclFrame.top ;

cxImage = cxImage * cxPix / cxMms / 100 ;

cyImage = cyImage * cyPix / cyMms / 100 ;

rect.left = (cxArea - cxImage) / 2 ;

rect.top = (cyArea - cyImage) / 2 ;

rect.right = (cxArea + cxImage) / 2 ;

rect.bottom = (cyArea + cyImage) / 2 ;

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 21

The CreateRoutine function in EMF11 is simpler than the one in EMF8 (our original ruler-metafile program)

because it does not need to call GetDeviceCaps to determine the resolution of the video display in dots per inch Instead, EMF11 calls SetMapMode to set the mapping mode to MM_LOENGLISH, where logical units are equal

to 0.01 inches Thus, the dimensions of the ruler are 600 units by 100 units, and these numbers are passed to

DrawRuler.

The DrawRuler function in EMF11 is the same as the one in EMF9, except for the MoveToEx and LineTo calls

that draw the tick marks of the ruler When drawing in units of pixels (the default MM_TEXT mapping mode), units

on the vertical axis increase going down the screen For the MM_LOENGLISH mapping mode (and the othermetrical mapping modes), they increase going up That required a change to this code The adjustment factors in the

Rectangle function were also changed.

The PaintRoutine function in EMF11 is basically the same as the one in EMF9, which was the version of the

program that successfully displayed the ruler in its correct dimensions on both the video display and the printer Theonly difference is that EMF11 uses the EMF11.EMF file, whereas EMF9 used the EMF8.EMF file created byEMF8

The image displayed by EMF11 is basically the same as EMF9 So, we see here how embedding a SetMapMode

call into a metafile can simplify the metafile creation and doesn't affect at all the mechanics of playing the metafile in itscorrect size

Mapping and Playing

Calculating the destination rectangle in EMF11 involves some calls to GetDeviceCaps Our second goal is to

eliminate those and use a mapping mode instead GDI treats the coordinates of the destination rectangle as logicalcoordinates Using the MM_HIMETRIC mode seems like a good candidate for these coordinates, because thatmakes logical units 0.01 millimeters, the same units used for the bounding rectangle in the enhanced metafile header

The EMF12 program shown in Figure 18-20 restores the DrawRuler logic as originally presented in EMF8 but uses

the MM_HIMETRIC mapping mode to display the metafile

Figure 18-20 The EMF12 program

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 22

TCHAR szClass [] = TEXT ("EMF12") ;

TCHAR szTitle [] = TEXT ("EMF12: Enhanced Metafile Demo #12") ;

void DrawRuler (HDC hdc, int cx, int cy)

{

int iAdj, i, iHeight ;

LOGFONT lf ;

TCHAR ch ;

iAdj = GetVersion () & 0x80000000 ? 0 : 1 ;

// Black pen with 1-point width

SelectObject (hdc, CreatePen (PS_SOLID, cx / 72 / 6, 0)) ;

// Rectangle surrounding entire pen (with adjustment)

Rectangle (hdc, iAdj, iAdj, cx + iAdj + 1, cy + iAdj + 1) ;

else iHeight = cy / 12 ; // sixteenths MoveToEx (hdc, i * cx / 96, cy, NULL) ;

LineTo (hdc, i * cx / 96, cy - iHeight) ;

}

// Create logical font

FillMemory (&lf, sizeof (lf), 0) ;

lf.lfHeight = cy / 2 ;

lstrcpy (lf.lfFaceName, TEXT ("Times New Roman")) ;

SelectObject (hdc, CreateFontIndirect (&lf)) ;

SetTextAlign (hdc, TA_BOTTOM | TA_CENTER) ;

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 23

/ Clean up

DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ; DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN))) ; }

hdcEMF = CreateEnhMetaFile (NULL, TEXT ("emf12.emf"), NULL,

TEXT ("EMF13\0EMF Demo #12\0")) ;

cxMms = GetDeviceCaps (hdcEMF, HORZSIZE) ;

cyMms = GetDeviceCaps (hdcEMF, VERTSIZE) ;

cxPix = GetDeviceCaps (hdcEMF, HORZRES) ;

cyPix = GetDeviceCaps (hdcEMF, VERTRES) ;

hemf = GetEnhMetaFile (TEXT ("emf12.emf")) ;

GetEnhMetaFileHeader (hemf, sizeof (emh), &emh) ;

cxImage = emh.rclFrame.right - emh.rclFrame.left ;

cyImage = emh.rclFrame.bottom - emh.rclFrame.top ;

Trang 24

The PaintRoutine function in EMF12 first sets the mapping mode to MM_HIMETRIC As with the other metric modes, values of y increase going up the screen However, the origin is still at the upper left corner, which means that

y-coordinates within the client area are negative To correct this oddity, the program calls SetViewportOrgEx to set

the origin to the lower left corner

The device point (cxArea, 0) is at the upper right corner of the screen Passing that point to the DPtoLP ("device

point to logical point") function gives us the size of the client area in 0.01 millimeters

The program then loads the metafile, gets the header, and finds the dimensions of the metafile in 0.01 millimeters Thedestination rectangle centered in the middle of the client area is then easy to calculate

Now we've seen how we can use a mapping mode when creating the metafile and also for displaying it Can we doboth?

It turns out that it works, as EMF13 (shown in Figure 18-21) demonstrates

Figure 18-21 The EMF13 program

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 25

TCHAR szClass [] = TEXT ("EMF13") ;

TCHAR szTitle [] = TEXT ("EMF13: Enhanced Metafile Demo #13") ;

cxImage = emh.rclFrame.right - emh.rclFrame.left ;

cyImage = emh.rclFrame.bottom - emh.rclFrame.top ;

Now we can establish a couple principles When the metafile is created, GDI uses any embedded changes to themapping mode to calculate the size of the metafile image in pixels and millimeters The size of the image is stored inthe metafile header When the metafile is played, GDI establishes the physical location of the destination rectangle

based on the mapping mode in effect at the time of the PlayEnhMetaFile call Nothing in the metafile can change

that location

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 26

Chapter 19

The Multiple-Document Interface

The Multiple-Document Interface (MDI) is a specification for applications that handle documents in MicrosoftWindows The specification describes a window structure and user interface that allow the user to work with multipledocuments within a single application (such as text documents in a word-processing program or spreadsheets in aspreadsheet program) Simply put, just as Windows maintains multiple application windows within a single screen, anMDI application maintains multiple document windows within a single client area The first MDI application forWindows was the first Windows version of Microsoft Excel But many others soon followed

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 27

MDI Concepts

Although the MDI specification has been around since Windows 2.0, at that time MDI applications were difficult towrite and required some very intricate programming work Since Windows 3.0, however, much of that work hasalready been done for you That support, with some enhancements from Windows 95, has been carried over intoWindows 98 and Microsoft Windows NT

The Elements of MDI

The main application window of an MDI program is conventional: it has a title bar, a menu, a sizing border, a systemmenu icon, and minimize/maximize/close buttons The client area, however, is often called a "workspace" and is notdirectly used to display program output This workspace contains zero or more child windows, each of which

displays a document

These child windows look much like normal application windows and much like the main application window of anMDI program They too have a title bar, a sizing border, a system menu icon, minimize/maximize/close buttons, andpossibly scroll bars None of the document windows has a menu, however The menu on the main application

window applies to the document windows

At any one time, only one document window is active (indicated by a highlighted title bar), and it appears in front ofall the other document windows All the document child windows are clipped to the workspace area and neverappear outside the application window

At first, MDI seems a fairly straightforward job for the Windows programmer All you need to do is create a

WS_CHILD window for each document, making the program's main application window the parent of the documentwindow But with a little exploration of existing MDI applications, you'll find some complications that require difficultcode

• An MDI document window can be minimized A short title bar with an icon appears at the bottom of theworkspace Generally, an MDI application will use different icons for the main application window and eachtype of document window

• An MDI document window can be maximized In this case, the title bar of the document window (normallyused to show the filename of the document in the window) disappears and the filename appears appended tothe application name in the application window's title bar The system menu icon of the document windowbecomes the first item in the top-level menu of the application window The button to close the documentwindow becomes the last item in the top-level menu and appears to the far right

• The system keyboard accelerator to close a document window is the same as that to close the main window,except that the Ctrl key is used rather than Alt That is, Alt-F4 closes the application window, while Ctrl-F4closes the document window In addition, Ctrl-F6 switches among the child document windows within theactive MDI application Alt-Spacebar invokes the system menu of the main window, as usual Alt (minus)invokes the system menu of the active child document window

• When using the cursor keys to move among items on the menu, control normally passes from the systemmenu to the first item on the menu bar In an MDI application, control passes from the application systemmenu to the active document system menu to the first item on the menu bar

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 28

• If the application is capable of supporting several types of child windows (for example, the worksheet andchart documents in Microsoft Excel), the menu should reflect the operations associated with that type ofdocument This requires that the program change the menu when a different document window becomesactive In addition, when no document window exists, the menu should be stripped down to only thoseoperations involved in opening or creating a new document

• The top-level menu bar has an item called Window By convention, this is the last item on the top-level menubar except for Help The Window submenu generally has options to arrange the document windows withinthe workspace Document windows can be "cascaded" from the upper left or "tiled" so that each documentwindow is fully visible This submenu also has a list of all the document windows Selecting one moves thatdocument window to the foreground

All of these aspects of MDI are supported in Windows 98 Some overhead is required of course (as will be shown in

a sample program), but it isn't anywhere close to the amount of code you'd have to write to support all these featuresdirectly

MDI Support

Some new terminology is necessary when approaching the Windows MDI support The main application window iscalled the "frame window." Just as in a conventional Windows program, this is a window of the

WS_OVERLAPPEDWINDOW style

An MDI application also creates a "client window" based on the predefined window class MDICLIENT The client

window is created by a call to CreateWindow using this window class and the WS_CHILD style The last argument

to CreateWindow is a pointer to a small structure of type CLIENTCREATESTRUCT This client window covers

the client area of the frame window and is responsible for much of the MDI support The color of this client window

is the system color COLOR_APPWORKSPACE

The document windows, as you've probably noticed, are called "child windows." You create these windows byinitializing a structure of type MDICREATESTRUCT and sending the client window a WM_MDICREATE messagewith a pointer to this structure

The document windows are children of the client window, which in turn is a child of the frame window The

parent-child hierarchy is shown in Figure 19-1

Figure 19-1 The parent-child hierarchy of a Windows MDI application

You need a window class (and window procedure) for the frame window and for each type of child window

supported by the application You don't need a window procedure for the client window because the window class

is preregistered

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 29

The MDI support of Windows 98 includes one window class, five functions, two data structures, and twelve

messages I've already mentioned the new window class, which is MDICLIENT, and the new data structures,

CLIENTCREATESTRUCT and MDICREATESTRUCT Two of the five functions replace DefWindowProc in MDI applications: rather than call DefWindowProc for all unprocessed messages, a frame window procedure calls

DefFrameProc and a child window procedure calls DefMDIChildProc Another function specific to MDI,

TranslateMDISysAccel, is used in the same way as TranslateAccelerator, which I discussed in Chapter 10 The

MDI support also includes ArrangeIconicWindows, but one of the special MDI messages makes this function

unnecessary for MDI programs

The fifth MDI function is called CreateMDIWindow This allows the child window to be created in a separate thread

of execution This function is not required in a single-threaded program, which is what I'll be demonstrating

In the sample program coming up, I'll demonstrate nine of the twelve MDI messages (The other three are not

normally required.) These messages begin with the prefix WM_MDI A frame window sends these messages to theclient window to perform an operation on a child window or to obtain information about a child window (Forexample, a frame window sends a WM_MDICREATE message to a client window to create a child window.) TheWM_MDIACTIVATE message is an exception: while a frame window can send this message to the client window

to activate one of the child windows, the client window also sends the message to the child windows being activatedand deactivated to inform them of this change

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 30

A Sample MDI Implementation

The MDIDEMO program, shown in Figure 19-2, demonstrates the basics of writing an MDI application

Figure 19-2 The MDIDEMO program

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 31

LRESULT CALLBACK FrameWndProc (HWND, UINT, WPARAM, LPARAM) ;

BOOL CALLBACK CloseEnumProc (HWND, LPARAM) ;

LRESULT CALLBACK HelloWndProc (HWND, UINT, WPARAM, LPARAM) ;

LRESULT CALLBACK RectWndProc (HWND, UINT, WPARAM, LPARAM) ;

// structure for storing data unique to each Hello child window typedef struct tagHELLODATA

TCHAR szAppName[] = TEXT ("MDIDemo") ;

TCHAR szFrameClass[] = TEXT ("MdiFrame") ;

TCHAR szHelloClass[] = TEXT ("MdiHelloChild") ;

TCHAR szRectClass[] = TEXT ("MdiRectChild") ;

HINSTANCE hInst ;

HMENU hMenuInit, hMenuHello, hMenuRect ;

HMENU hMenuInitWindow, hMenuHelloWindow, hMenuRectWindow ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 32

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1) ;

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ;

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ;

hMenuInit = LoadMenu (hInstance, TEXT ("MdiMenuInit")) ;

hMenuHello = LoadMenu (hInstance, TEXT ("MdiMenuHello")) ;

hMenuRect = LoadMenu (hInstance, TEXT ("MdiMenuRect")) ;

hMenuInitWindow = GetSubMenu (hMenuInit, INIT_MENU_POS) ;

hMenuHelloWindow = GetSubMenu (hMenuHello, HELLO_MENU_POS) ;

hMenuRectWindow = GetSubMenu (hMenuRect, RECT_MENU_POS) ;

// Load accelerator table

hAccel = LoadAccelerators (hInstance, szAppName) ;

// Create the frame window

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 33

NULL, hMenuInit, hInstance, NULL) ;

hwndClient = GetWindow (hwndFrame, GW_CHILD) ;

if (!TranslateMDISysAccel (hwndClient, &msg) &&

!TranslateAccelerator (hwndFrame, hAccel, &msg))

LRESULT CALLBACK FrameWndProc (HWND hwnd, UINT message,

WPARAM wParam, LPARAM lParam)

hwndClient = CreateWindow (TEXT ("MDICLIENT"), NULL,

WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,

Trang 34

if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0))

SendMessage (hwndClient, WM_MDIDESTROY,

default: // Pass to active child

hwndChild = (HWND) SendMessage (hwndClient,

Trang 35

LRESULT CALLBACK HelloWndProc (HWND hwnd, UINT message,

WPARAM wParam, LPARAM lParam)

{

static COLORREF clrTextArray[] = { RGB (0, 0, 0), RGB (255, 0, 0), RGB (0, 255, 0), RGB ( 0, 0, 255), RGB (255, 255, 255) } ;

static HWND hwndClient, hwndFrame ;

pHelloData = (PHELLODATA) HeapAlloc (GetProcessHeap (),

HEAP_ZERO_MEMORY, sizeof (HELLODATA)) ;

Trang 36

DrawText (hdc, TEXT ("Hello, World!"), -1, &rect,

DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;

SendMessage (hwndClient, WM_MDISETMENU,

(WPARAM) hMenuHello, (LPARAM) hMenuHelloWindow) ;

// Check or uncheck menu item

pHelloData = (PHELLODATA) GetWindowLong (hwnd, 0) ;

CheckMenuItem (hMenuHello, pHelloData->iColor,

(lParam == (LPARAM) hwnd) ? MF_CHECKED : MF_UNCHECKED) ;

// Set the Init menu if losing focus

Trang 37

break ; // i.e., call DefMDIChildProc

case WM_DESTROY:

pHelloData = (PHELLODATA) GetWindowLong (hwnd, 0) ;

HeapFree (GetProcessHeap (), 0, pHelloData) ;

LRESULT CALLBACK RectWndProc (HWND hwnd, UINT message,

WPARAM wParam, LPARAM lParam)

int xLeft, xRight, yTop, yBottom ;

short nRed, nGreen, nBlue ;

pRectData = (PRECTDATA) HeapAlloc (GetProcessHeap (),

HEAP_ZERO_MEMORY, sizeof (RECTDATA)) ;

SetWindowLong (hwnd, 0, (long) pRectData) ;

pRectData->cxClient = LOWORD (lParam) ;

pRectData->cyClient = HIWORD (lParam) ;

pRectData = (PRECTDATA) GetWindowLong (hwnd, 0) ;

xLeft = rand () % pRectData->cxClient ;

xRight = rand () % pRectData->cxClient ;

yTop = rand () % pRectData->cyClient ;

yBottom = rand () % pRectData->cyClient ;

nRed = rand () & 255 ;

nGreen = rand () & 255 ;

nBlue = rand () & 255 ;

Trang 38

Rectangle (hdc, min (xLeft, xRight), min (yTop, yBottom),

max (xLeft, xRight), max (yTop, yBottom)) ;

pRectData = (PRECTDATA) GetWindowLong (hwnd, 0) ;

HeapFree (GetProcessHeap (), 0, pRectData) ;

Trang 39

MDIMENUINIT MENU DISCARDABLE

BEGIN

POPUP "&File"

BEGIN

MENUITEM "New &Hello", IDM_FILE_NEWHELLO

MENUITEM "New &Rectangle", IDM_FILE_NEWRECT

MENUITEM "New &Hello", IDM_FILE_NEWHELLO

MENUITEM "New &Rectangle", IDM_FILE_NEWRECT

MENUITEM "&Close", IDM_FILE_CLOSE

MENUITEM "&Black", IDM_COLOR_BLACK

MENUITEM "&Red", IDM_COLOR_RED

MENUITEM "&Green", IDM_COLOR_GREEN

MENUITEM "B&lue", IDM_COLOR_BLUE

MENUITEM "&White", IDM_COLOR_WHITE

END

POPUP "&Window"

BEGIN

MENUITEM "&Cascade\tShift+F5", IDM_WINDOW_CASCADE

MENUITEM "&Tile\tShift+F4", IDM_WINDOW_TILE

MENUITEM "Arrange &Icons", IDM_WINDOW_ARRANGE

MENUITEM "Close &All", IDM_WINDOW_CLOSEALL

MENUITEM "New &Hello", IDM_FILE_NEWHELLO

MENUITEM "New &Rectangle", IDM_FILE_NEWRECT

MENUITEM "&Close", IDM_FILE_CLOSE

MENUITEM SEPARATOR

MENUITEM "E&xit", IDM_APP_EXIT

END

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Trang 40

POPUP "&Window"

BEGIN

MENUITEM "&Cascade\tShift+F5", IDM_WINDOW_CASCADE

MENUITEM "&Tile\tShift+F4", IDM_WINDOW_TILE

MENUITEM "Arrange &Icons", IDM_WINDOW_ARRANGE

MENUITEM "Close &All", IDM_WINDOW_CLOSEALL

END

END

///////////////////////////////////////////////////////////////////////////// // Accelerator

MDIDEMO ACCELERATORS DISCARDABLE

BEGIN

VK_F4, IDM_WINDOW_TILE, VIRTKEY, SHIFT, NOINVERT

VK_F5, IDM_WINDOW_CASCADE, VIRTKEY, SHIFT, NOINVERT

END

This document is created with the unregistered version of CHM2PDF Pilot

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Ngày đăng: 13/08/2014, 08:20

TỪ KHÓA LIÊN QUAN