翻译 tellmenow
在下面的DOIView示例程序中,演示了资源、键盘加速键和弹出式菜单的用法。DOIView是Declaration of Independence View的缩写,显示了美国独立宣言。程序中的文本被存储为一系列字符串资源。DOIView将文本格式化来适应程序窗口,并使用滚动条来滚动文本。
图4-3显示了DOIView窗口。按Ctr-H和Ctr-E可以将文档滚动到开头和结尾。您也可以在窗口上点压来显示一个快捷菜单,用来快速滚动到文档开头、结尾以及结束程序。
图4-3(略):显示快捷菜单的DOI View窗口
DOIView的源文件显示在清单4-2中。请注意第3个包含文件DOIView.rc,它包含了程序的资源脚本。DOIView.rc包含有菜单资源,包含一行程序使用的图标,还包含一个字符串表,里面是用来显示的文字。因为字符串资源被限制为4092个字符,所以文字被包含在多个字符串里。
清单4-2:DOIView 程序
DOIView.rc
//======================================================================
// DOIView - Resource file
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//
//======================================================================
#include "DOIView.h"
//----------------------------------------------------------------------
// Icon
//
ID_ICON ICON "DOIView.ico"
//----------------------------------------------------------------------
// Menu
//
ID_MENU MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Goto Start/tCtrl-H", IDM_HOME
MENUITEM "&Goto End/tCtrl-E", IDM_END
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
END
END
//----------------------------------------------------------------------
// Accelerator table
//
ID_ACCEL ACCELERATORS DISCARDABLE
BEGIN
"H", IDM_HOME, VIRTKEY, CONTROL
"E", IDM_END, VIRTKEY, CONTROL
END
//----------------------------------------------------------------------
// String table
//
STRINGTABLE DISCARDABLE
BEGIN
IDS_DOITEXT, "IN CONGRESS, July 4, 1776./012The unanimous /
Declaration of the thirteen united States of America,/012WHEN in the /
Course of human Events, it becomes necessary for one People to /
dissolve the Political Bands which have connected them with another, /
and to assume among the Powers of the Earth, the separate and equal /
Station to which the Laws of Nature and of Nature's God entitle them, /
a decent Respect to the Opinions of Mankind requires that they should /
declare the causes which impel them to the Separation./012/
WE hold these Truths to be self-evident, that all Men are created /
equal, that they are endowed by their Creator with certain /
unalienable Rights, that among these are Life, Liberty and the Pursuit /
of Happiness -- That to secure these Rights, Governments are /
instituted among Men, deriving their just Powers from the Consent of /
the Governed, that whenever any Form of Government becomes destructive /
of these Ends, it is the Right of the People to alter or to abolish /
it, and to institute new Government, laying its Foundation on such /
Principles, and organizing its Powers in such Form, as to them shall /
seem most likely to effect their Safety and Happiness. Prudence, /
indeed, will dictate that Governments long established should /
not be changed for light and transient Causes; and accordingly all /
Experience hath shewn, that Mankind are more disposed to suffer, while /
Evils are sufferable, than to right themselves by abolishing the Forms /
to which they are accustomed. But when a long Train of Abuses and /
Usurpations, pursuing invariably the same Object, evinces a Design to /
reduce them under absolute Despotism, it is their Right, it is their /
Duty, to throw off such Government, and to provide new Guards for /
their future Security. Such has been the patient Sufferance of these /
Colonies; and /
such is now the Necessity which constrains them to alter their /
former Systems of Government. The History of the present King of Great /
Britain is a History of repeated Injuries and Usurpations, all having /
in direct Object the Establishment of an absolute Tyranny over these /
States. To prove this, let Facts be submitted to a candid World./012/
HE has refused his Assent to Laws, the most wholesome and /
necessary for the public Good./012HE has forbidden his Governors to /
pass Laws of immediate and pressing Importance, unless suspended in /
their Operation till his Assent should be obtained; and when so /
suspended, he has utterly neglected to attend to them./012/
HE has refused to pass other Laws for the Accommodation of large /
Districts of People, unless those People would relinquish the Right of /
Representation in the Legislature, a Right inestimable to them, and /
formidable to Tyrants only./012HE has called together Legislative /
Bodies at Places unusual, uncomfortable, and distant from the /
Depository of their public Records, for the sole Purpose of fatiguing /
them into Compliance with his Measures./012/
HE has dissolved Representative Houses repeatedly, for opposing /
with manly Firmness his Invasions on the Rights of the People./012HE /
has refused for a long Time, after such Dissolutions, to cause others /
to be elected; whereby the Legislative Powers, incapable of the /
Annihilation, have returned to the People at large for their exercise; /
the State remaining in the mean time exposed to all the Dangers of /
Invasion from without, and the Convulsions within./012/
HE has endeavoured to prevent the Population of these States; /
for that Purpose obstructing the Laws for Naturalization of Foreigners/
; refusing to pass others to encourage their Migrations hither, and /
raising the Conditions of new Appropriations of Lands./012HE has /
obstructed the Administration of Justice, by refusing his Assent to /
Laws for establishing Judiciary Powers./012HE has made Judges /
dependent on his Will alone, for the Tenure of their Offices, and the /
Amount and Payment of their Salaries./012"
IDS_DOITEXT1, "HE has erected a Multitude of new Offices, and sent /
hither Swarms of Officers to harrass our People, and eat out their /
Substance./012HE has kept among us, in Times of Peace, Standing /
Armies, without the consent of our Legislatures./012HE has affected to /
render the Military independent of and superior to the Civil Power./012/
HE has combined with others to subject us to a Jurisdiction /
foreign to our Constitution, and unacknowledged by our Laws; giving /
his Assent to their Acts of pretended Legislation:/012FOR quartering /
large Bodies of Armed Troops among us;/012FOR protecting them, by a /
mock Trial, from Punishment for any Murders which they should commit /
on the Inhabitants of these States:/012FOR cutting off our Trade with /
all Parts of the World:/012/
FOR imposing Taxes on us without our Consent:/012FOR depriving /
us, in many Cases, of the Benefits of Trial by Jury:/012FOR /
transporting us beyond Seas to be tried for pretended Offences:/012/
FOR abolishing the free System of English Laws in a neighbouring /
Province, establishing therein an arbitrary Government, and enlarging /
its Boundaries, so as to render it at once an Example and fit /
Instrument for introducing the same absolute Rules into these /
Colonies:/012/
FOR taking away our Charters, abolishing our most valuable Laws, /
and altering fundamentally the Forms of our Governments:/012FOR /
suspending our own Legislatures, and declaring themselves invested /
with Power to legislate for us in all Cases whatsoever./012HE has /
abdicated Government here, by declaring us out of his Protection and /
waging War against us./012HE has plundered our Seas, ravaged our /
Coasts, burnt our Towns, and destroyed the Lives of our People./012/
HE is, at this Time, transporting large Armies of foreign /
Mercenaries to compleat the Works of Death, Desolation, and Tyranny, /
already begun with circumstances of Cruelty and Perfidy, scarcely /
paralleled in the most barbarous Ages, and totally unworthy the Head /
of a civilized Nation./012HE has constrained our fellow Citizens taken /
Captive on the high Seas to bear Arms against their Country, to become /
the Executioners of their Friends and Brethren, or to fall themselves /
by their Hands./012/
HE has excited domestic Insurrections amongst us, and has /
endeavoured to bring on the Inhabitants of our Frontiers, the /
merciless Indian Savages, whose known Rule of Warfare, is an /
undistinguished Destruction, of all Ages, Sexes and Conditions./012IN /
every stage of these Oppressions we have Petitioned for Redress in the /
most humble Terms: Our repeated Petitions have been answered only by /
repeated Injury. A Prince, whose Character is thus marked by every act /
which may define a Tyrant, is unfit to be the Ruler of a free People. /
NOR have we been wanting in Attentions to our Brittish Brethren. /
We have warned them from Time to Time of Attempts by their Legislature /
to extend an unwarrantable Jurisdiction over us. We have reminded them /
of the Circumstances of our Emigration and Settlement here. We have /
appealed to their native Justice and Magnanimity, and we have conjured /
them by the Ties of our common Kindred to disavow these Usurpations, /
which, would inevitably interrupt our Connections and Correspondence. /
They too have been deaf to the Voice of Justice and of Consanguinity. /
We must, therefore, acquiesce in the Necessity, which denounces our /
Separation, and hold them, as we hold the rest of Mankind, Enemies in /
War, in Peace, Friends./012"
IDS_DOITEXT2, "WE, therefore, the Representatives of the UNITED /
STATES OF AMERICA, in GENERAL CONGRESS, Assembled, appealing to the /
Supreme Judge of the World for the Rectitude of our Intentions, do, in /
the Name, and by Authority of the good People of these Colonies, /
solemnly Publish and Declare, That these United Colonies are, and of /
Right ought to be, FREE AND INDEPENDENT STATES; that they are absolved /
from all Allegiance to the British Crown, and that all political /
Connection between them and the State of Great-Britain, is and ought /
to be totally dissolved; and that as FREE AND INDEPENDENT STATES, they /
have full Power to levy War, conclude Peace, contract Alliances, /
establish Commerce, and to do all other Acts and Things which /
INDEPENDENT STATES may of right do. And for the support of this /
Declaration, with a firm Reliance on the Protection of divine /
Providence, we mutually pledge to each other our Lives, our Fortunes, /
and our sacred Honor."
END
DOIView.h
//======================================================================
// Header file
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//================================================================
// Returns number of elements
#define dim(x) (sizeof(x) / sizeof(x[0]))
//----------------------------------------------------------------------
// Generic defines and data types
//
struct decodeUINT { // Structure associates
UINT Code; // messages
// with a function.
LRESULT (*Fxn)(HWND, UINT, WPARAM, LPARAM);
};
struct decodeCMD { // Structure associates
UINT Code; // menu IDs with a
LRESULT (*Fxn)(HWND, WORD, HWND, WORD); // function
};
#define ID_MENU 10
#define ID_ACCEL 11
#define IDM_HOME 100
#define IDM_END 101
#define IDM_EXIT 102
#define IDS_DOITEXT 1000 // These IDs must be
#define IDS_DOITEXT1 1001 // consecutive
#define IDS_DOITEXT2 1002
//----------------------------------------------------------------------
// Function prototypes
//
LPTSTR WrapString (HDC hdc, LPTSTR pszText, int *pnLen, int nWidth,
BOOL *fEOL);
HWND InitInstance (HINSTANCE, LPWSTR, int);
int TermInstance (HINSTANCE, int);
// Window procedures
LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM);
// Message handlers
LRESULT DoCreateMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoSizeMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCommandMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoLButtonDownMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoRButtonUpMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoVScrollMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoPaintMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoDestroyMain (HWND, UINT, WPARAM, LPARAM);
// Command functions
LPARAM DoMainCommandHome (HWND, WORD, HWND, WORD);
LPARAM DoMainCommandEnd (HWND, WORD, HWND, WORD);
LPARAM DoMainCommandExit (HWND, WORD, HWND, WORD);
DOIView.cpp
//======================================================================
// DOIView - Demonstrates window scroll bars
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include <windows.h> // For all that Windows stuff
#include "DOIView.h" // Program-specific stuff
#include <aygshell.h> // Extended shell API
//----------------------------------------------------------------------
// Global data
//
const TCHAR szAppName[] = TEXT("DOIView");
HINSTANCE hInst; // Program instance handle
#define WM_MYMSG (WM_USER + 100)
// Message dispatch table for MainWindowProc
const struct decodeUINT MainMessages[] = {
WM_CREATE, DoCreateMain,
WM_SIZE, DoSizeMain,
WM_LBUTTONDOWN, DoLButtonDownMain,
WM_COMMAND, DoCommandMain,
WM_VSCROLL, DoVScrollMain,
WM_PAINT, DoPaintMain,
WM_DESTROY, DoDestroyMain,
};
// Command Message dispatch for MainWindowProc
const struct decodeCMD MainCommandItems[] = {
IDM_HOME, DoMainCommandHome,
IDM_END, DoMainCommandEnd,
IDM_EXIT, DoMainCommandExit,
};
typedef struct {
LPTSTR pszLine;
int nLen;
} LINEARRAY, *PLINEARRAY;
#define MAXLINES 1000
LINEARRAY laText[MAXLINES];
int nNumLines = 0;
int nFontHeight = 1;
int nLinesPerPage = 1;
LPTSTR pszDeclaration;
HFONT hFont;
int nVPos, nVMax;
BOOL fFirst = TRUE;
//======================================================================
// Program entry point
//
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow) {
MSG msg;
int rc = 0;
HWND hwndMain;
HACCEL hAccel;
// Initialize this instance.
hwndMain = InitInstance (hInstance, lpCmdLine, nCmdShow);
if (hwndMain == 0) return 0x10;
// Load accelerator table.
hAccel = LoadAccelerators (hInst, MAKEINTRESOURCE (ID_ACCEL));
// Application message loop
while (GetMessage (&msg, NULL, 0, 0)) {
// Translate accelerators
if (!TranslateAccelerator (hwndMain, hAccel, &msg)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
// Instance cleanup
return TermInstance (hInstance, msg.wParam);
}
//----------------------------------------------------------------------
// InitInstance - Instance initialization
//
HWND InitInstance (HINSTANCE hInstance, LPWSTR lpCmdLine, int nCmdShow) {
WNDCLASS wc;
HWND hWnd;
PBYTE pRes, pBuff;
int nStrLen = 0, i = 0;
// Save program instance handle in global variable.
hInst = hInstance;
#if defined(WIN32_PLATFORM_PSPC)
// If Pocket PC, only allow one instance of the application
hWnd = FindWindow (szAppName, NULL);
if (hWnd) {
SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
return 0;
}
#endif
// Load text from multiple string resources into one large buffer
pBuff = (PBYTE)LocalAlloc (LPTR, 8);
while (pRes = (PBYTE)LoadString (hInst, IDS_DOITEXT + i++, NULL, 0))
{
// Get the length of the string resource
int nLen = *(PWORD)(pRes-2) * sizeof (TCHAR);
// Resize buffer
pBuff = (PBYTE)LocalReAlloc (pBuff, nStrLen + 8 + nLen,
LMEM_MOVEABLE | LMEM_ZEROINIT);
if (pBuff == NULL) return 0;
// Copy resource into buffer
memcpy (pBuff + nStrLen, pRes, nLen);
nStrLen += nLen;
}
*(TCHAR *)(pBuff + nStrLen) = TEXT ('/0');
pszDeclaration = (LPTSTR)pBuff;
// Register application main window class.
wc.style = 0; // Window style
wc.lpfnWndProc = MainWndProc; // Callback function
wc.cbClsExtra = 0; // Extra class data
wc.cbWndExtra = 0; // Extra window data
wc.hInstance = hInstance; // Owner handle
wc.hIcon = NULL, // Application icon
wc.hCursor = LoadCursor (NULL, IDC_ARROW);// Default cursor
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wc.lpszMenuName = NULL; // Menu name
wc.lpszClassName = szAppName; // Window class name
if (RegisterClass (&wc) == 0) return 0;
// Create main window.
hWnd = CreateWindowEx (WS_EX_NODRAG, szAppName,
TEXT("The Declaration of Independence"),
WS_VSCROLL | WS_VISIBLE | WS_CAPTION |
WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL,
NULL, hInstance, NULL);
if (!IsWindow (hWnd)) return 0; // Fail code if not created.
// Standard show and update calls
ShowWindow (hWnd, nCmdShow);
UpdateWindow (hWnd);
return hWnd;
}
//----------------------------------------------------------------------
// TermInstance - Program cleanup
//
int TermInstance (HINSTANCE hInstance, int nDefRC) {
LocalFree (pszDeclaration);
return nDefRC;
}
//======================================================================
// Message handling procedures for main window
//
//----------------------------------------------------------------------
// MainWndProc - Callback function for application window
//
LRESULT CALLBACK MainWndProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
int i;
//
// Search message list to see if we need to handle this
// message. If in list, call procedure.
//
for (i = 0; i < dim(MainMessages); i++) {
if (wMsg == MainMessages[i].Code)
return (*MainMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
}
return DefWindowProc (hWnd, wMsg, wParam, lParam);
}
//----------------------------------------------------------------------
// DoCreateMain - Process WM_CREATE message for window.
//
LRESULT DoCreateMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
TEXTMETRIC tm;
HDC hdc = GetDC (hWnd);
LOGFONT lf;
HFONT hFontWnd;
hFontWnd = (HFONT)GetStockObject (SYSTEM_FONT);
GetObject (hFontWnd, sizeof (LOGFONT), &lf);
lf.lfHeight = -12 * GetDeviceCaps(hdc, LOGPIXELSY)/ 72;
lf.lfWeight = 0;
hFont = CreateFontIndirect (&lf);
SendMessage (hWnd, WM_SETFONT, (WPARAM)hFont, 0);
// Get the height of the default font.
hFontWnd = (HFONT)SelectObject (hdc, hFont);
GetTextMetrics (hdc, &tm);
nFontHeight = tm.tmHeight + tm.tmExternalLeading;
SelectObject (hdc, hFontWnd);
ReleaseDC (hWnd, hdc);
return 0;
}
//----------------------------------------------------------------------
// DoSizeMain - Process WM_SIZE message for window.
//
LRESULT DoSizeMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
RECT rect;
HDC hdc = GetDC (hWnd);
GetClientRect (hWnd, &rect);
int i = 0, nChars, nWidth;
LPTSTR pszWndText = pszDeclaration;
SCROLLINFO si;
HFONT hFontWnd;
BOOL fNewLine;
hFontWnd = (HFONT)SelectObject (hdc, hFont);
// Compute the line breaks
nWidth = rect.right - rect.left - 10;
while (i < MAXLINES){
pszWndText = WrapString (hdc, pszWndText, &nChars, nWidth,
&fNewLine);
if (pszWndText == 0)
break;
laText[i].pszLine = pszWndText;
laText[i].nLen = nChars;
i++;
if (fNewLine) {
laText[i].nLen = 0;
i++;
}
pszWndText += nChars;
}
nNumLines = i;
nLinesPerPage = (rect.bottom - rect.top)/nFontHeight;
// Compute lines per window and total lenght
si.cbSize = sizeof (si);
si.nMin = 0;
si.nMax = nNumLines;
si.nPage = nLinesPerPage;
si.nPos = nVPos;
si.fMask = SIF_ALL;
SetScrollInfo (hWnd, SB_VERT, &si, TRUE);
// Clean up
SelectObject (hdc, hFontWnd);
ReleaseDC (hWnd, hdc);
InvalidateRect (hWnd, NULL, TRUE);
return 0;
}
//----------------------------------------------------------------------
// DoCommandMain - Process WM_COMMAND message for window.
//
//
LRESULT DoCommandMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
WORD idItem, wNotifyCode;
HWND hwndCtl;
int i;
// Parse the parameters.
idItem = (WORD) LOWORD (wParam);
wNotifyCode = (WORD) HIWORD(wParam);
hwndCtl = (HWND) lParam;
// Call routine to handle control message.
for (i = 0; i < dim(MainCommandItems); i++) {
if (idItem == MainCommandItems[i].Code)
return (*MainCommandItems[i].Fxn)(hWnd, idItem, hwndCtl,
wNotifyCode);
}
return 0;
}
//----------------------------------------------------------------------
// DoLButtonDownMain - Process WM_LBUTTONDOWN message for window.
//
LRESULT DoLButtonDownMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
HMENU hMenuMain, hMenu;
POINT pt;
int rc;
// Display the menu at the point of the tap
pt.x = LOWORD (lParam);
pt.y = HIWORD (lParam);
SHRGINFO sri;
sri.cbSize = sizeof (sri);
sri.dwFlags = 1;
sri.hwndClient = hWnd;
sri.ptDown = pt;
// See if tap and hold
rc = SHRecognizeGesture (&sri);
if (rc == 0) return 0;
// Display the menu at the point of the tap
// First, convert to desktop coordinates
MapWindowPoints (hWnd, HWND_DESKTOP, &pt, 1);
pt.x += 5;
hMenuMain = LoadMenu (hInst, MAKEINTRESOURCE (ID_MENU));
hMenu = GetSubMenu (hMenuMain, 0);
TPMPARAMS tpm;
tpm.cbSize = sizeof (tpm);
GetClientRect (hWnd, &tpm.rcExclude);
TrackPopupMenuEx (hMenu, TPM_LEFTALIGN | TPM_TOPALIGN,
pt.x, pt.y, hWnd, &tpm);
DestroyMenu (hMenuMain);
DestroyMenu (hMenu);
return 0;
}
//----------------------------------------------------------------------
// DoVScrollMain - Process WM_VSCROLL message for window.
//
LRESULT DoVScrollMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
RECT rect;
SCROLLINFO si;
int sOldPos = nVPos;
GetClientRect (hWnd, &rect);
switch (LOWORD (wParam)) {
case SB_LINEUP:
nVPos -= 1;
break;
case SB_LINEDOWN:
nVPos += 1;
break;
case SB_PAGEUP:
nVPos -= nLinesPerPage;
break;
case SB_PAGEDOWN:
nVPos += nLinesPerPage;
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
nVPos = HIWORD (wParam);
break;
}
// Check range.
if (nVPos < 0)
nVPos = 0;
if (nVPos > nNumLines-1)
nVPos = nNumLines-1;
// If scroll position changed, update scrollbar and
// force redraw of window.
if (nVPos != sOldPos) {
si.cbSize = sizeof (si);
si.nPos = nVPos;
si.fMask = SIF_POS;
SetScrollInfo (hWnd, SB_VERT, &si, TRUE);
InvalidateRect (hWnd, NULL, TRUE);
}
return 0;
}
//----------------------------------------------------------------------
// DoPaintMain - Process WM_PAINT message for window.
//
LRESULT DoPaintMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
PAINTSTRUCT ps;
HFONT hFontWnd;
RECT rect;
HDC hdc;
int i, y = 5;
hdc = BeginPaint (hWnd, &ps);
GetClientRect (hWnd, &rect);
hFontWnd = (HFONT)SelectObject (hdc, hFont);
// Draw the text
for (i = nVPos; i < nNumLines; i++) {
if (y > rect.bottom - nFontHeight - 10)
break;
if (laText[i].nLen)
ExtTextOut (hdc, 5, y, TRANSPARENT, NULL, laText[i].pszLine,
laText[i].nLen, NULL);
y += nFontHeight;
}
SelectObject (hdc, hFontWnd);
EndPaint (hWnd, &ps);
return 0;
}
//----------------------------------------------------------------------
// DoDestroyMain - Process WM_DESTROY message for window.
//
LRESULT DoDestroyMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
PostQuitMessage (0);
return 0;
}
//======================================================================
// Command handler routines
//
//----------------------------------------------------------------------
// DoMainCommandHome - Process Program Home command.
//
LPARAM DoMainCommandHome (HWND hWnd, WORD idItem, HWND hwndCtl,
WORD wNotifyCode) {
SCROLLINFO si;
if (nVPos != 0) {
nVPos = 0;
si.cbSize = sizeof (si);
si.nPos = nVPos;
si.fMask = SIF_POS;
SetScrollInfo (hWnd, SB_VERT, &si, TRUE);
InvalidateRect (hWnd, NULL, TRUE);
}
return 0;
}
//----------------------------------------------------------------------
// DoMainCommandEnd - Process End command.
//
LPARAM DoMainCommandEnd (HWND hWnd, WORD idItem, HWND hwndCtl,
WORD wNotifyCode) {
SCROLLINFO si;
int nEndPos = nNumLines - nLinesPerPage + 1;
if (nVPos != nEndPos) {
nVPos = nEndPos;
si.cbSize = sizeof (si);
si.nPos = nVPos;
si.fMask = SIF_POS;
SetScrollInfo (hWnd, SB_VERT, &si, TRUE);
InvalidateRect (hWnd, NULL, TRUE);
}
return 0;
}
//----------------------------------------------------------------------
// DoMainCommandExit - Process Program Exit command.
//
LPARAM DoMainCommandExit (HWND hWnd, WORD idItem, HWND hwndCtl,
WORD wNotifyCode) {
SendMessage (hWnd, WM_CLOSE, 0, 0);
return 0;
}
//----------------------------------------------------------------------
// WrapString - Determine a length that will fit with a width
//
LPTSTR WrapString (HDC hdc, LPTSTR pszText, int *pnLen, int nWidth,
BOOL *fEOL) {
LPTSTR pszStr, pszStart;
SIZE Size;
*fEOL = FALSE;
*pnLen = 0;
// Skip to first non-space char
for (; (*pszText!=TEXT('/0')) && (*pszText<=TEXT (' ')); pszText++);
pszStart = pszText;
if (*pszText == 0)
return 0;
while (1) {
pszStr = pszText;
// Find end of the next word
for (; (*pszText!=TEXT('/0')) && *pszText>TEXT (' ');pszText++);
// Get length of the string
GetTextExtentPoint (hdc, pszStart, pszText - pszStart, &Size);
if (Size.cx > nWidth)
break;
if ((*pszText == TEXT ('/0')) || (*pszText == TEXT ('/r')) ||
(*pszText == TEXT ('/n'))) {
*fEOL = TRUE;
pszStr = pszText;
break;
}
// slip past space
pszText++;
}
*pnLen = pszStr - pszStart;
return pszStart;
}
程序启动的时候,会将字符串资源读到一个大的缓冲区中。通过传递一个NULL缓冲区给LoadString函数来访问字符串资源,可以减少对内存的影响。这将使LoadString返回一个指向资源的指针。注意,在这种情况下,字符串并不是以零结尾的,所以DOIView从字符串之前的一个字里,读取字符的个数。因为字符串是Unicode,字符串长度应该是再乘以TCHAR的大小,由此得到字符串需要的缓冲区的尺寸。
DOIView的主窗口处理了一些额外消息。WM_SIZE消息处理例程中通过调用WrapString重新格式化了文本。该例程调用了GetTextExtentPoint来计算每行的长度。如果长度小于窗口宽度,例程就给该行增加一个单词,并重新计算长度。这会一直持续到该行被加的单词长度达到窗口宽度时为止。WM_PAINT消息处理例程则从当前滚动位置所定义的用来显示的文本行开始绘制。
WM_VSCROLL例程处理来自垂直滚动条的消息。当通知是SB_PAGEUP或者SB_PAGEDOWN的时候,该例程会在当前滚动位置上减少或者增加要显示的行数。WM_LBUTTONDOWN例程从菜单资源中装载一个菜单。该菜单有三个命令:Home表示滚动到文档起始位置;End表示滚动到文档结尾;Exit表示退出程序。DOIView还响应加速键:Ctrl-H用于Home,Ctrl-E用于End.
从基础的子窗口到控件以及资源和菜单,本章函盖了大量的基础内容。我的目的不是教这些主题里的每个东西。相反,我试图介绍每个程序元素,提供一些示例,并指出Windows CE和Windows桌面版本处理这些元素的细微差别。
虽然Windows控件很有用并且相当方便,但下一章节会涉及一些通用控件。这些控件是Windows CE也支持的功能更强大,也更复杂的控件集。