Windows CE Programming
Windows CE Programming
Contents
About this Book
Acknowledgments
-----------
Contents
Contents at a Glance
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Introduction to Windows CE 1
Windows CE Operating System 13
Handheld PC Hardware 31
Visual C++ for Windows CE 51
Hello Windows CE 75
User Interface Basics 99
Controls 137
Input and Output 209
Registry and File System 251
Windows CE Databases 279
Windows CE Help Files 323
Windows CE Application Loader 353
File Filters 373
Remote API Functions 399
Table of Contents
1 Introduction to Windows CE 1
Windows CE History 2
WinPad 2
Pulsar 2
Pegasus 3
Future of Windows CE 4
Windows CE References 5
Handheld PC Manufacturers 5
Microsoft Windows CE Site 5
Other WWW Sites 6
Newsgroups 6
FAQs 7
Mailing Lists 7
Magazines 8
About This Book 8
2 Windows CE Operating System 13
Windows CE Components 14
Shell 14
Control Panel 16
Applications 17
Kernel 17
Graphics, Windowing, and Events Subsystem 18
Memory Architecture 21
Object Store 22
Power Management 23
Notifications 24
Communications 25
Desktop Connectivity 25
Remote API 26
Help System 26
Unicode 26
Windows CE API 27
Porting Applications to Windows CE 29
3 Handheld PC Hardware 31
Handheld PC Components 32
Microprocessor 32
Memory 33
Screen 34
Page 7
Keyboard 36
Stylus 36
Audio 37
Serial Port 37
Infrared Port 38
LED 39
PCMCIA Slot 39
Handheld PC Manufacturers 40
Casio Cassiopeia 40
NEC MobilePro 42
Compaq PC Companion 43
LG Electronics 45
Hitachi 46
HP 300LX, 320LX 47
Philips Velo 1 49
4 Visual C++ for Windows CE 51
Development Environment 52
Installing Visual C++ for Windows CE 52
Remote Connection and RAS settings 53
Components of Visual C++ for Windows CE 56
Creating Windows CE Applications 60
Building Applications 60
Debugging Applications 61
Shell Emulation 63
Windows CE Remote Tools 64
Handheld PC Explorer 64
<DIV> 338
<DL> 338
<DT> 338
<EM> 338
<FONT> 338
<Hn> 339
<HEAD> 340
<HR> 340
<HTML> 340
<I> 341
<IMG> 341
<KBD> 342
<LI> 342
<LISTING> 342
<MENU> 342
<META> 343
<NOBR> 343
<OL> 343
<P> 344
<PLAINTEXT> 344
<PRE> 344
<S> 345
<SAMP> 345
<SMALL> 345
<STRIKE> 345
<STRONG> 345
<SUB> 345
<SUP> 346
<TABLE> 346
<TD> 346
<TH> 347
<TITLE> 347
<TR> 347
<TT> 347
<U> 348
<UL> 348
<VAR> 348
<WBR> 348
<XMP> 349
TravelManager Pocket Help Use 349
Page 13
12 Windows CE Application Loader 353
Application Loader Functions 354
Load_AlreadyInstalled 354
Load_Exit 355
Load_Init 355
Load_PegCpuType 355
Load_PegFreeSpace 356
Load_RegisterFileInfo 356
Load 357
The Load Script File 359
The Unload Script 359
Load File Commands 360
appendToUnload 361
copy 361
copyShared 363
createShortcut 364
execOnUnload 365
exit 365
mkdir 365
prependToUnload 366
regInt 366
regKeyCreate 367
regString 368
regValueDelete 369
remoteExec 369
TravelManager Installation 370
13 File Filters 373
File Filter Overview 374
Filter Direction 374
Registry Entries 375
Extension Key 375
CLSID Key 377
Registry Entries Example 378
Null File Filters 379
File Filter Components 380
IPegasusFileFilter Interface 381
IPegasusFileFilterSite Interface 387
File Filter Structures 391
File Filter Process 393
File Filter Example 394
Page 14
14 Remote API Functions 399
Remote API Overview 400
Using RAPI Functions 400
Available RAPI Functions 402
RAPI Support Functions 403
Object Store Functions 404
Database Functions 409
Registry Functions 411
Window Management Functions 412
System Functions 412
RAPI Example 420
Kevin Fulcher
Page 3
Acknowledgments
First I would like to thank all the folks at Macmillan Technical Publishing,
especially Jim LeValley and Amy Lewis, for their assistance, guidance, and
patience in this project. Brad Miser was also very helpful in the initial content
editing phase of this project.
I would like to thank Carl Sampson who got me started in this project in the
first place. Thanks to Bryan Everly and everyone at Software Artistry for
understanding the impact this project has had on my "day job."
To all my family and friends who uged me on by the repeated, "Is the book
done yet?"I'm glad I can finally say "yes."
Finally, I can't forget to thank the most important person on this project, my
wife Melanie. She kept me going, prodded me on, and
generaly put up with all late nights and lonely weekends that I spent in front of
the compuyter. It looks like my 8-month project will finish just slightly ahead
of her 9-month project.
Jeff Baker
[email protected]
June 30, 1997
Previous | Table of Contents | Next
CHAPTER 1
Introduction to Windows CE
In the fall of 1996, Microsoft introduced the newest member of the Windows
family of operating systems: Windows CE. Windows CE is a small, 32-bit,
platform-independent operating system positioned for a wide range of
hardware applications.
The initial focus of the Windows CE operating system is on a new set of
devices for the hand-held computer market. Microsoft has given the new
category of computers the name Handheld PC. This new terminology reflects
the desire by Microsoft and its partners to set the Handheld PC apart from the
current generation of Personal Digital Assistant (PDA) devices or personal
organizers.
A Handheld PC running Windows CE is designed to be a mobile companion to
the desktop PC (running Microsoft Windows 95, of course). Windows CE
provides users with a familiar interface, and supports many forms of data
synchronization between the Handheld PC and the desktop PC.
So what does the CE stand for? Compact Edition? Consumer Electronics?
Committee Endorsed? Can't Explain? Well, officially, it doesn't stand for
anything, just like NT doesn't (currently) stand for anything. Apparently, many
suffixes were considered and CE won out. Microsoft officials say that the CE
suffix is a lot like the LX or ES that is used with many automobile models in
that it doesn't really stand for anything although it sounds like it should.
Page 2
Windows CE History
Although branded a 1.0 release, Microsoft has been working to develop
hand-held computing technology for at least five years. The WinPad and
Pulsar projects were the ancestors of Windows CE, but those projects never
made it to market.
WinPad
In 1992, Microsoft began work on a stripped-down version of Windows 3.1
that would be used to produce a Windows-based handheld computer. Like
Apple's Newton, WinPad did not have a keyboard, but did employ handwriting
recognition technology as its means of input.
WinPad was intended to be a mobile companion to the desktop PC. WinPad
could be connected to the desktop PC through a serial connection. Once
connected, data would be automatically synchronized between the WinPad
device and the desktop PC. Applications for WinPad were written in Visual
Basic.
Many factors influenced the ultimate demise of the WinPad project. The
estimated consumer price of building a WinPad device was around $900,
probably more than buyers would be willing to pay. The Apple Newton had
failed to live up to its hype and consequently negatively affected the entire
PDA market. Finally, the handwriting recognition technology of the time was
slow and error-prone, making data entry difficult.
Pulsar
In the fall of 1993, another project, named Pulsar, was started by the Advanced
Technology group at Microsoft. The goal of the Pulsar project was to create a
new "super-pager" that allowed individuals to communicate with each other
and with services over two-way wireless networks.
Page 3
Pulsar was positioned as a consumer device, not a desktop companion tool like
WinPad. Aimed primarily at noncomputer users, Pulsar used a
"social-interface" like General Magic's Magic Cap, or the more recent
Microsoft Bob.
The Pulsar device was roughly the size of a large pager and therefore
(obviously) contained no keyboard. Input to the device was done through an
on-screen keyboard. Programming on the Pulsar device was also largely done
with Visual Basic.
Early consumer testing of the Pulsar revealed that the small size of the device
and lack of a keyboard were serious drawbacks. In addition, most people felt
that this was not a device they needed or would be willing to pay a monthly fee
to use.
Pegasus
In late 1994, Microsoft decided to combine the two handheld device efforts
into one group, under the code name, Pegasus. Like the WinPad project, the
overall goal was to create a mobile device that would be a companion to the
desktop PC (running a Windows operating system).
Other goals of the Pegasus project included to deliver a device with a
price-point near $500, create a platform suitable for communication, and to
provide an open development environment for building Pegasus applications.
Overall, the goal was to create a useful PC companion tool, not a super-PDA.
None of the WinPad code was carried over into the Pegasus project. The
Pulsar team, however, had developed a lightweight Win32-subset kernel that
evolved into the Windows CE operating system.
The Pegasus project continued through 1995, eventually adopting the
Windows 95 interface and becoming Windows CE. By early 1996, hardware
developers became partners on the project and were creating prototype
devices. A beta program was also launched so developers could start building
applications for this new operating system.
Page 4
At Comdex in the fall of 1996, Microsoft officially announced the Pegasus
project, now christened "Windows CE." A few manufacturers released their
Handheld PCs at that time while other Handheld PCs were not released until
the spring and early summer of 1997. At the time of this writing, seven
manufacturers produce Handheld PCs. Chapter 3, "Handheld PC Hardware,"
lists information on each of the devices.
Future of Windows CE
Not only has Windows CE surpassed its WinPad and Pulsar ancestors by
actually making it to market, it also appears to have a bright future.
There are currently over 3,000 independent software vendors building
applications for Windows CE. The applications range from PIM applications
that perform simple tasks such as managing a grocery list, to complex
applications for retail sales clerks and healthcare professionals. Many new
companies have been created to focus on Windows CE and the new markets
that have emerged around it.
At the time of this writing, Microsoft is well underway with the next major
version of the Windows CE operating system. Windows CE 2.0 is scheduled
to include new platform support, new technology support (ActiveX and Java),
LAN connectivity, and color display support.
In addition to adding features to the operating system, Windows CE will likely
be used in other types of devices. The devices might include something simple
such as a phone or pager, or something complex such as an onboard navigation
and control system in an automobile. The current generation of Handheld PCs
could also be adapted to larger devices (bigger keyboards and color screens),
or smaller devices such as a wallet-sized device.
Windows CE is designed to be suitable for many different systems. Anything
with a display interface is a likely target: cash register, gasoline pump, ATM,
and so on. The possibilities are nearly endlessalthough it will likely be quite
some time before Windows CE is controlling your toaster
Previous | Table of Contents | Next
CHAPTER 2
Windows CE Components
Windows CE can be broken down into many different components, including
the kernel and user interface. This section details the major components of
Windows CE.
Note that the descriptions presented here relate to Windows CE as used on
Handheld PCs (currently the only available devices that use Windows CE).
The major functions of Windows CE are separated into components so that
device manufacturers can essentially pick and choose the parts that they need
for their particular device that may or may not be an HPC (obviously, it is not
quite that simple). Future devices using Windows CE, for instance, may have
substantially different interfaces than the interface used on Handheld PCs.
Shell
When you first turn on the Handheld PC, Windows CE starts, displaying the
Windows CE desktop. The desktop looks almost identical to a shrunken
version of the Windows 95 or Windows NT 4.0 desktop, as shown in Figure
2.1.
The shell contains the familiar Start button in the lower-left corner. The
Windows CE Start button offers the same functionality as it does under
Windows 95. Clicking the Start button displays a menu of options for
accessing help, running a program, exploring the file system, launching the
Control Panel, and shutting down the device.
Page 15
Figure 2.1
The Windows CE
desktop.
The taskbar displays a "button" for each of the currently running applications.
Clicking a button brings the corresponding application to the front, just like it
does in Windows 95. A new feature in the Windows CE taskbar is the ability
to minimize the currently active window by clicking its corresponding button
on the taskbar.
The right side of the taskbar displays a clock and an area for notification icons.
The small icons display status information (such as if your device is using A/C
power or if the batteries are low) or notify the user of various events (such as if
you are connected to a desktop PC or you set the alarm). Applications can add
icons to this area as needed.
The remainder of the desktop above the taskbar is an area for shortcuts to
applications or folders as well as special icons for the Recycle Bin and My
Handheld PC. The My Handheld PC icon launches the Windows CE Explorer,
which you use to navigate files and folders on the Handheld PC.
Page 16
Control Panel
Like in Windows 95, you adjust settings for Windows CE using applets found
in the Control Panel folder. To access the Control Panel, choose the Settings
menu option on the Start menu.
The following applets are standard in Windows CE:
Backlight. Changes screen backlighting options (only present on devices
with backlighting).
Communications. Changes device name and dial-out settings.
Display. Changes background wallpaper and contrast settings.
Keyboard. Changes delay and repeat rates.
Owner. Changes owner profile.
Password. Changes owner password and security settings.
Power. Changes power management options.
Remove Programs. Uninstalls programs from the device.
Stylus. Calibrates touch screen and sets double tap rate.
System. Changes memory settings and displays system information.
Volume and Sounds. Changes volume and event sounds.
World Clock. Changes date, time, and alarm options.
Windows CE also supports the ability to create user-defined Control Panel
applets. Applications can install their own Control Panel applets (with the .cpl
extension) in the \Windows directory.
The Control Panel applet has the same structure under Windows CE as it does
under Windows 95. The Control Panel and the applet communicate through
messages sent to the CPlApplet function of the applet. Windows CE uses the
same messages as Windows 95, except for CPL_SELECT.
Previous | Table of Contents | Next
Page 11
Chapter 8, "Input and Output," explores input and output mechanisms
for interacting with the user, including keyboard, stylus, timers,
graphics, and notifications.
Chapter 9, "Registry and File System," details the registry and file
system support in Windows CE and the differences of those same
components in other versions of Windows.
Chapter 10, "Windows CE Databases," describes the database
functionality that is built into Windows CE and that can be utilized in
Windows CE applications.
Chapter 11, "Windows CE Help Files," details the new help engine
present in Windows CE.
Chapter 12, "Windows CE Application Loader," describes the process
of installing a Windows CE application onto the Handheld PC device.
Chapter 13, "File Filters," examines the construction and operation of
file filters, which allow data files to be converted when transferred from
the desktop PC to the Handheld PC or vice versa.
Chapter 14, "Remote API Functions," describes the functions available
to a Windows 95 application on the desktop PC that can directly
manipulate data on a connected Handheld PC.
Appendix A, "Getting Started with the CD-ROM," details how to access
the sample source code and executable files contained on the CD-ROM.
Page 12
Previous | Table of Contents | Next
Windows CE References
There is a lot of information currently available about Windows CE, and the
volume of that information is certainly going to increase. There are many great
Web sites devoted to Windows CE, as well as newsgroups, mailing lists,
books, and magazines.
Handheld PC Manufacturers
Currently there are seven manufacturers with Windows CE-based Handheld
PCs. All of the manufacturers have web sites, which are listed in the following
table.
Site Name
Casio Cassiopeia
Compaq PC
Companion
Hewlett-Packard
300LX, 320LX
Hitachi Handheld PC
URL
http://www.casiohpc.com
LG Handheld PC
http://www.lgeus.com/hpc
http://www.nec.com
NEC MobilePro
Philips Velo 1
http://www.compaq.com/us/
common/prodinfo/handhelds
http://www.hp.com/handheld
http://www.hitachi.com
http://www.velo1.com
URL
http://www.windowsce.com
http://homepages. enterprise.net/craig/
windowsce.html
http://hotpocket.com
http://www.hpcpage.com
http://www.ziplink.net/
~maxm/windowsce/index.html
http://members.aol.com/
pcdchrisd/wce/wce.htm
http://www.microsoft.com/
isapi/hwtest/hsearchce.idc
http://www.arcos.org/worlds/
Newsgroups
Newsgroups, or Usenet newsgroups, are electronic bulletin boards where
people can share information. Access to a news server is required to read
information from or post questions to a newsgroup.
Microsoft provides a news server (msnews.microsoft.com) that has multiple
newsgroups relevant to Windows CE. The microsoft.public. windowsce
newsgroup contains general Windows CE information, microsoft.vc.vcce
covers Visual C++ for Windows CE, and
Page 7
microsoft.programmer.win32.wince offers information on programming with
Windows CE.
Currently, no Usenet newsgroups are dedicated to Windows CE, although
occasionally some contain content on Windows CE. The comp.sys.palmtops
and comp.sys.handhelds newsgroups cover a broad range of devices that
include Windows CE.
FAQs
FAQs, or Frequently Asked Questions, have become a common source of
information with the popularity of the Internet. A FAQ for a particular subject
or product can be created and maintained by the official source of that product,
or by someone interested in spreading information about that technology. The
following table lists some of the FAQ lists that have recently appeared for
Windows CE.
Site Name
Microsoft
Windows CE
FAQ
Craig Peacock's
Windows CE
FAQ
Chris
DeHerrera's
Windows CE
FAQ
URL
http://www.microsoft.com/
windowsce/hpc/home/faq.htm
http://homepages. enterprise.net/craig/hpc/
cefaq.html
http://members.aol.com/
pdcchrisd/wce/wcefaq.htm
Mailing Lists
Mailing lists are similar to newsgroups, except that when you post a message,
it is sent as an e-mail message to everyone on the mailing list. Currently, two
mailing lists cover Windows CE. Use the http://www.dillernet.com/wince.html
Web site to join Andy Diller's Windows CE mailing list and
http://cgi.skyweyr.comwindowscetalk.home to subscribe to WindowsCE.com's
Windows CE Talk mailing list.
Page 8
Magazines
Although nearly every magazine that covers the Windows operating system
has done articles on Windows CE, some magazines cover Windows CE
regularly. The following table lists the current magazines (print and electronic)
that cover Windows CE along with their Web sites.
Magazine
Mobile Worker
Magazine
Mobilis
Magazine
Handheld PC
Magazine
Handheld
Systems Journal
Pen Computing
Magazine
URL
http://www.microsoft.com/
windowsce/hpc/mobile
http://www.volksware.com/ mobilis
http://www.thaddeus.com/ wince/hpc.htm
http://www.cdpubs.com/ hhsj.html
http://www.pencomputing.com
Mobile
Computing
PMN
Publications
http://www.mobilecomputing .com
http://www.pmn.co.uk
Although the Control Panel applet has the same structure under Windows CE
and Windows 95, an applet compiled for Windows 95 will not directly run
under Windows CE.
Applications
Windows CE includes many applications that make the Handheld PC very
functional right out of the box. The standard Windows CE applications include
the following:
Microsoft Pocket Word. A subset of the Microsoft Word word processor
application.
Microsoft Pocket Excel. A subset of the Microsoft Excel spreadsheet
application.
Pocket Internet Explorer. Windows CE's Web browser.
Inbox. An application for sending and receiving e-mail.
Calendar. A scheduler for managing appointments and events.
Contacts. An electronic address book.
Tasks. Electronic "to-do" lists.
Calculator. A simple on-screen calculator.
Terminal. A simple terminal emulation program.
World Clock. Displays date and time for multiple cities.
Solitaire. Windows' standard game.
Kernel
The fact that Windows CE is small and lightweight definitely does not equate
to it being a less powerful operating system. The Windows CE kernel, which
was rewritten specifically for non-PC devices, implements the Win32 process,
thread, and virtual memory model. The system is limited to 32 processes, but
Windowing
Applications are not notified before the power is shut off. However, device
drivers are notified when the system is being suspended and have the
capability to stop the power from being shut off (if they are receiving data, for
instance).
Notifications
Notifications are the mechanism Windows CE uses to communicate with the
user and Windows CE-based applications. A notification is a signal from the
operating system that an event has occurred. Windows CE includes a new set
of API functions to work with notifications. An application registers a
notification for an event, and Windows CE generates a notification when the
event occurs.
Windows CE supports two types of notifications: user and application. A user
notification alerts the user about a timed event, such as an appointment. Based
on user preferences, the system notifies the user by flashing an external LED,
displaying a dialog box, or playing a sound. An application notification alerts
an application of system events, such as AC power state, PCMCIA card
insertion, and communication connections.
See Chapter 8, "Input and Output," for more information on Windows CE
Notifications.
Page 25
Communications
As a remote device, communication is an important issue with Handheld PCs.
Windows CE supports a variety of communication protocols for
communicating with other devices.
Windows CE supported communication application programming interfaces
consist of a subset of WinSock (version 1.1), Remote Access Service (RAS)
connection and management functions, Win32 serial functions, and a subset of
the Telephony API (TAPI).
Windows CE supports most of the common WinSock functions. It exposes
TCP/IP and IrDA through the WinSock API.
Most of the procedures and issues with communications programming are no
different under Window CE than under other Windows versions. Because the
supported communication mechanisms in Windows CE are a very large
subject, it is not included in this general Windows CE programming book.
Desktop Connectivity
One of the key features of Windows CE and the Handheld PC is simple and
seamless synchronization with the desktop PC. Users access this feature by
using the Handheld PC Explorer application on the desktop PC to transfer files
and synchronize their PIM data.
Applications can be programmed such that they have access to the desktop
connectivity functionality. Windows CE has added new API functionality for
Remote API
Another new set of functionality in Windows CE is the set of Remote API
(RAPI) functions. This API is a set of functions that can be called from an
application running on the desktop PC, but which is actually executed on the
remote Windows CE device.
Windows CE supports RAPI functions for performing file management,
database management, registry functions, and some miscellaneous system
management functions.
The RAPI functions are implemented as a thin layer on the top of the actual
Windows CE API calls. In most cases, the RAPI calls take the same arguments
and have the same behavior as the local Windows CE functions.
See Chapter 14, "Remote API Functions," for more information on the
Windows CE Remote API.
Help System
Windows CE is the first operating system of the Windows family to abandon
WinHelp as the help system. The extreme space limitations on Windows CE
devices make the Windows WinHelp mechanism impractical.
Windows CE introduces a new help system in which the help files are
authored in the HyperText Markup Language (HTML). The Windows CE help
system, Pocket Help, supports basic formatting such as jumps, bitmaps, and
tables.
See Chapter 11, "Windows CE Help Files," for more information on Windows
CE help files.
Unicode
Windows CE API
Although Windows CE was designed and written from scratch, Microsoft
chose to make the Application Programming Interface (API) for Windows CE
a subset of Microsoft's Win32 API. Win32API is used to build applications for
Windows 95 and Windows NT. This choice greatly benefits the thousands of
experienced Windows programmers who are already working with the Win32
API.
However, because Windows CE requires only 105 KB of ROM and about 400
KB of RAM to run, numerous Win32 pieces had to be excluded to create an
operating system that small; Windows CE only supports about 500 of the 2000
or so Win32 APIs.
Page 28
Although supporting only 1/4 of Win32 APIs seems like a very small portion,
most of the missing functions are contained in technology that Windows CE
does not support. Some of the areas that Windows CE does not support include
the following:
OLE
COM
ActiveX
MAPI
ODBC
DDE
Printing
Multimedia
DirectX
Console applications
Security
Help
Named events
Interapplication synchronization
APIs for 16-bit compatibility
CHAPTER 3
Handheld PC Hardware
The first device to use the Windows CE operating system is the Handheld PC;
in fact, the Handheld PC was specifically designed to run Windows CE.
The Handheld PC is a new category of computera mobile companion as well
as a device that brings Windows to the palm of your hand. The Handheld PC is
more powerful than other electronic organizers, yet seems easy to use because
of the similarity between the Windows CE interface and the Windows 95 or
Windows NT 4.0 interfaces.
Rather than building the hardware for Handheld PCs itself, Microsoft
partnered with seven well-known hardware manufacturers who developed the
first Handheld PCs. Microsoft defined a reference platform on which the
manufacturers created their own versions of the Handheld PCs.
Using an approach it has taken in other markets, Microsoft defined a minimal
hardware specification for the Handheld PC, but allowed each manufacturer to
add other capabilities and features. The key requirements for Handheld PC
hardware are:
A pocket form factor; size should not exceed 7"4"1"
Power is supplied by two AA batteries
Lightweight; Handheld PCs should weigh less than 1 pound
Previous | Table of Contents | Next
Page 32
A QWERTY keyboard containing standard keys (including Ctrl, Alt,
Shift)
An LCD touch screen display of at least 480240 pixels with 4
grayscales and 2 bits per pixel
A stylus to use like a mouse on the touch screen
A minimum of 4 MB of ROM and 2 MB of RAM
An infrared port
A serial port
A PCMCIA slot
A built-in audio output device
The first section of this chapter details the specific hardware components that
make up the Handheld PC. The second section describes the specifications and
features of each of the current Handheld PC models.
Handheld PC Components
As the name implies, a Handheld PC is a personal computer. As such, the
Handheld PC has most of the same components as a traditional personal
computer. These components are detailed in the following sections.
Microprocessor
To achieve the goal of making Windows CE a suitable operating system for a
wide range of devices, Windows CE supports a variety of microprocessors.
The microprocessor architectures currently supported are the Hitachi SH3, the
MIPS (R3000/R4000), and Intel x86 series (for the emulation environment).
The specific chip sets used in the initial generation of Handheld PCs are the
Hitachi SH3, the NEC MIPS VR4101, and the Philips TwoChipPIC (MIPS
processor). All the current chip sets are based on RISC architecture.
Given the design of Windows CE, other 32-bit processors can be readily
supported by porting the Windows CE kernel and building the
cross-compilers. Microsoft, for example, has recently announced Windows CE
support for the Arm, StrongArm, and PowerPC processors.
An important factor in Handheld PC devices is the balance between processor
speed and power consumption. Windows CE is constantly looking for power
savings by switching the CPU operating mode.
Handheld PC microprocessors have three different modes of operation
designed to minimize power consumption: The Full Speed mode is used when
applications are executing; The Standby mode is used during brief idle periods
and uses less than one-tenth the power of full-speed mode; The Suspend mode
is used during long idle periods and uses less than one-thousandth the power of
Full Speed mode.
Because the processor is such a significant consumer of power when running,
applications should return control to the operating system whenever possible.
Unnecessarily running the CPU (for example, in a PeekMessage loop) will
consume power and can usually be handled differently.
Because each of the supported processors for Windows CE uses different
instruction sets, application developers must produce a binary image of their
application for each processor. Luckily, the Windows CE development
environment does most of the work by allowing the creation of multiple binary
images from one set of source code.
Related to the microprocessor, Handheld PCs have two hardware timers. The
first hardware timer is a high-resolution timer that provides scheduling
interrupts and timer events. The second hardware timer is a low-resolution
real-time clock that maintains the current data and time for the Handheld PC.
Memory
The reference design for the Handheld PC specifies a 480240 pixel liquid
crystal display type. Windows CE currently only supports a
Previous | Table of Contents | Next
monochrome display with 2 bits per pixel. This allows for four colors: black,
white, light gray, and dark gray.
The Handheld PC screen is a continuous resistive touch panel that gives the
user the ability to select items on the screen without using a mouse. Handheld
PCs all come with a stylus, although any pointing device (such as your finger)
works with the touch screen.
The display contrast can be changed by the user to accommodate different
lighting conditions. The contrast is adjusted either by a dial on the side of the
case, or by using the Alt+< and Alt+> key combinations.
Another feature of the screen is backlighting. Many manufacturers add
backlighting support to the Handheld PC display. Backlighting enhances the
ability to read the screen in low-light or no-light situations. Of course, the
negative aspect of backlighting is that it increases power consumption and will
therefore drain the batteries faster.
Some manufacturers have also enhanced the Handheld PC screen as a point of
differentiation. The Hewlett-Packard device uses a 640240 pixel display,
which is wider than all the other Handheld PCs. The Hitachi and LG
Electronics Handheld PCs use a .26mm dot-pitch as opposed to other
companies which opt for a .24mm dot-pitch. This larger dot-pitch supposedly
makes the screen more readable.
NOTE
The optimal solution bases the presentation of information on the
screen size. An application can call GetSystemMetrics (with
SM_CXSCREEN and SM_CYSCREEN) to get information on
the size of the screen and adjust its output accordingly.
Dealing with the limited screen real estate, varying screen sizes, and other
display limitations of Windows CE devices are some of the biggest challenges
Keyboard
Because Windows CE does not currently include built-in handwriting
recognition, all Handheld PCs include a QWERTY-style keyboard. The
keyboard includes the standard extra keys such as Ctrl, Alt, and two Shift keys.
Most also include the new "Windows" key.
The specific shape and feel of the keyboard is one of the features that most
differentiates the various Handheld PC devices: Some devices use square keys
while others use oval keys; some devices use hard-plastic keys while others
use softer rubbery keys.
Enhancing the keyboard for additional functionality is a common theme
among manufacturers. The Hewlett-Packard device, for example, added a
keyboard sequence for generating the British pound symbol while the Philips
device features keyboard accelerators (Alt+1, Alt+2, and so on) for quickly
launching most built-in applications (Pocket Word, Calendar, and so on).
Programmatically, the keyboard functions the same under Windows CE as
under Windows 95. Keyboard events are sent to applications through familiar
Windows 95 messages such as the following:
WM_KEYUP, WM_KEYDOWN, WM_CHAR,
See Chapter 8, "Input and Output," for more information on keyboard
processing.
Stylus
All Handheld PCs are equipped with a stylus for use with the touch-sensitive
display (although the touch screen does not require the stylus to operate). The
stylus replaces a mouse for use as a point-and-select device.
Although the method for generating the mouse and stylus events is quite
different between Windows CE and other versions of Windows, the way
applications interpret those events is quite similar. Windows CE uses the same
WM_LBUTTONDOWN, WM_LBUTTONUP, and
Previous | Table of Contents | Next
Page 38
CreateFile
ReadFile
WriteFile
CloseHandle
GetCommState
SetCommState
EscapeCommFunction
GetCommTimeouts
SetCommTimeouts
SetCommMask
WaitCommEvent
GetCommModemStatus
Infrared Port
All of the current Handheld PC devices include an infrared communications
port. Windows CE supports infrared communications hardware that conforms
to the industry standardInfrared Data Association's (IrDA) specifications.
The initial version of Windows CE supports infrared connectivity from
Handheld PC to Handheld PC onlyconnectivity to infrared-enabled desktop
PCs is not currently supported. However, the Hewlett-Packard Handheld PC
does support printing to a Hewlett-Packard printer through the infrared port.
Programmatically, Windows CE supports the IrDA standard via the WinSock
API. The specification for Infrared Sockets (IrSock) provides extensions to
WinSock for infrared link communication channel. The following functions
are supported for IrSock. Some of those functions include the following
modifications incorporated for IrDA:
Page 39
Accept
Bind
Closesocket
Connect
Getsockopt
Listen
Recv
Send
Setsockopt
Socket
LED
Some Handheld PCs include an externally visible LED of which the primary
function is to notify the user of an event. The LED flashes until the user
handles or fixes the notification. Windows CE provides API functions for
setting notifications, which includes flashing the LED.
Refer to Chapter 8 for information on programmatically creating notifications
that include flashing the LED.
PCMCIA Slot
Each of the current Handheld PCs incorporates a PCMCIA slot that can be
used to add devices to the system, such as modems or flash-RAM cards, while
Windows CE includes built-in support for many PCMCIA devices. In
addition, Windows CE supports installable device drivers, so PCMCIA
manufacturers can create client drives for their devices. Taking it a step
further, Visual C++ for Windows CE currently includes the Device Driver Kit
(DDK) necessary for creating device drivers for Windows CE.
Handheld PC Manufacturers
This section lists the specifications and features of all currently available
Handheld PCs.
Note that some details common to all the Handheld PCs are not re-listed for
each Handheld PC model. For example, all the current Handheld PCs come
with a stylus, so it is not included in these lists.
Casio Cassiopeia
Casio was the first manufacturer to begin working with Microsoft on the
Windows CE project and the first to reach the new Handheld PC market with
its Cassiopeia device. Casio provides three models of the Cassiopeia. The
major differences between the models lie in the amount of RAM included, not
to mention the fact that one model includes a docking cradle and AC power
Table 3.1
Cassiopeia Hardware Specifications
Category
Models:
Size:
Weight:
CPU:
CPU Speed:
Screen (pixels):
Screen (diagonal):
Screen dot pitch:
Backlight:
Power Supply:
ROM:
Description
A-10, A-11, A-11Plus
6.9"3.6"1"
13.4 ounces
Hitachi SH3
40 MHz
480240
5.1 inches
.24 mm
Yes
Two AA alkaline or NiMH batteries
4 MB
2 MB (A-10), 4 MB (A-11), 6 MB
RAM:
(A-11Plus)
PCMCIA:
One built-in slot
Interfaces:
Serial port, Infrared port
Audio:
Built-in speaker
Indicator LED:
Yes, for alarms
Additional features: CD-ROM of additional applications
The following is a list of optional accessories available with the Casio
Cassiopeia:
Docking Station
Docking station set (includes docking station, AC adapter, rechargeable
battery pack, and charger)
MiniDock
Previous | Table of Contents | Next
Page 42
MiniDock Set (includes MiniDock and AC adapter)
Rechargeable battery pack
Charger for rechargeable battery pack
Data Communications Cable (to connect Casio digital camera)
NEC MobilePro
The NEC MobilePro Handheld PC is the only device to use the NEC Vr4101
MIPS processor. NEC claims this processor has the best performance per watt
ratio of all the current Handheld PC devices. Another way in which it contrasts
with the current Handheld PCs is the MobilePro's softer rubbery keyboard
keys, which is a small feature that some users might appreciate. Table 3.2 lists
the hardware specifications of the MobilPro.
Table 3.2
NEC MobilePro Hardware Specifications
Category
Models:
Size:
Weight:
CPU:
CPU Speed:
Screen (pixels):
Screen (diagonal):
Screen dot pitch:
Backlight:
Power Supply:
ROM:
Description
200, 400
6.89"3.74"1.03"
12.8 ounces
NEC Vr4101
33 MHz
480240
5.1 inches
.24 mm
No
Two AA alkaline or NiMH batteries
8 MB
RAM:
2 MB (200), 4 MB (400)
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
Catergory
PCMCIA:
Interfaces:
Audio:
Indicator LED:
Description
One built-in slot
Serial port, Infrared port
Built-in speaker
Yes, for alarms
Description
C120, C140, C120+
6.9"3.6"1"
continues
Previous | Table of Contents | Next
Table 3.3
Companion Hardware Specifications, continued
Category
Weight:
CPU:
CPU Speed:
Screen (pixels):
Screen (diagonal):
Screen dot pitch:
Backlight:
Power Supply:
ROM:
RAM:
PCMCIA:
Interfaces:
Audio:
Indicator LED:
Description
13.4 ounces
Hitachi SH3
40 MHz
480240
5.1 inches
.24 mm
Yes
Two AA alkaline or NiMH batteries
4 MB
2 MB (C120, C120+), 4 MB
(C140)
One built-in slot
Serial port, Infrared port
Built-in speaker
Yes, for alarms
The following optional accessories are available for the Compaq Companion:
2 MB memory expansion
10 MB Flash RAM
14.4 LP PC card modem
Combo Pack (includes AC adapter and Quick Connect cradle)
Power Pack (includes AC adapter, Quick Connect cradle, NiMH battery
pack, and battery charger)
Convenience cradle
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
Page 45
Stylus 3-Pack
Carrying Case
Slipcase
LG Electronics
LG Electronics enters the Handheld PC market with its GP40M device. The differentiating features of the GP40M
include a larger dot-pitch in the screen, a built-in microphone, and an optional built-in 14.4 modem. Table 3.4 lists
available hardware specifications for the GP40M.
Table 3.4
GP40M Hardware Specifications
Category
Model:
Size:
Weight:
CPU:
CPU Speed:
Screen (pixels):
Screen (diagonal):
Screen dot pitch:
Backlight:
Power Supply:
ROM:
RAM:
PCMCIA:
Interfaces:
Description
GP40M
6.45"3.76"1"
11.4 ounces
Hitachi SH3
40 MHz
480240
5.6 inches
.26 mm
No
Two AA alkaline or NiMH batteries
4 MB
2 MB, 4 MB
One built-in slot
Serial port, Infrared port
continues
Previous | Table of Contents | Next
Table 3.4
GP40M Hardware Specifications, continued
Category
Audio:
Indicator LED:
Additional Features:
Description
Built-in speaker and microphone
Yes, for alarms
CD-ROM of additional applications
The GP40M Handheld PC has the option of a 14.4 modem; however, it does
not occupy PCMCIA slot.
Hitachi
Although Hitachi manufactures the microprocessor for all but two of the
devices, it does not build its own Handheld PC. The Hitachi Handheld PC is
manufactured by LG Electronics and differs from the GP40M only in color
and labeling. Table 3.5 lists the available hardware specifications.
Table 3.5
Hitachi Handheld PC Hardware Specifications
Category
Models:
Size:
Weight:
CPU:
CPU Speed:
Screen (pixels):
Screen (diagonal):
Screen dot pitch:
Description
HPW10E2, HPW10E4
6.45"3.76"1"
11.4 ounces
Hitachi SH3
40 MHz
480240
5.6 inches
.26 mm
Backlight:
No
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
Category
Power Supply:
ROM:
RAM:
PCMCIA:
Interfaces:
Audio:
Indicator LED:
Additional Features:
Description
Two AA alkaline or NiMH batteries
4 MB
2 MB (HPW10E2), 4 MB (HPW10E4)
One built-in slot
Serial port, Infrared port
Built-in speaker and microphone
Yes, for alarms
CD-ROM of additional applications
Similar to LG Technologies' GP40M, the optional accessory available is a 14.4 modem; however, it does not occupy
PCMCIA slot.
HP 300LX, 320LX
The Hewlett-Packard Handheld PC is the most unique among the current set of devices because it uses a bigger screen.
The screen is considerably wider640 pixels instead of 480. The HP device also includes limited printing support and
additional applications in the ROM chip (see Table 3.6).
Table 3.6
HP Handheld PC Hardware Specifications
Category
Models:
Size:
Weight:
CPU:
CPU Speed:
Screen (pixels):
Description
300LX, 320LX
7.2"3.67"1.1"
15.6 ounces
Hitachi SH3
44 MHz
640240
continues
Previous | Table of Contents | Next
Table 3.6
HP Handheld PC Hardware Specifications, continued
Category
Screen (diagonal):
Screen dot pitch:
Backlight:
Power Supply:
ROM:
RAM:
PCMCIA:
Interfaces:
Audio:
Indicator LED:
Description
6.5 inches
.24 mm
Yes (in 320LX only)
Two AA alkaline or NiMH batteries
5 MB
2 MB (300LX), 4 MB (320LX)
One built-in slot
Serial port, Infrared port
Built-in speaker
No
CD-ROM of additional applications;
Printing support; Data backup to PC card;
Additional applications in ROM;
Additional Features:
Embedded numeric keypad (uses M, J, K,
L, U, I, O, 7, 8, 9 keys); CompactFlash
slot in 320LX
The following optional accessories are available for the HP Handheld PC:
HP docking cradle (included with 320LX)
HP AC adapter
HP CompactFlash memory
HP leather case
Spare styluses
Philips Velo 1
Philips differentiates its Velo 1 in the Handheld PC market by providing a unique design and additional features. The
exterior of the case is a very sleek dark blue and metallic combination with a rubbery feel. The interior features a stylish
keyboard with rounded keys that are both attractive and functional (see Table 3.7).
The additional features of the Velo 1 include a microphone that can be used to record speech even when the device is
closed, and a built-in 19.2 modem with an angled phone jack on the left side of the display screen.
Table 3.7
Velo 1 Hardware Specifications
Category
Description
Models:
4 MB, 4 MB Rechargeable
Size:
6.75"3.75"1.25"
Weight:
13.8 ounces
CPU:
MIPS R3910
CPU Speed:
36.864 MHz
Screen (pixels): 480240
Screen (diagonal): 5.1 inches
Screen dot pitch: .24 mm
Backlight:
Yes
Power Supply:
Two AA alkaline or NiMH batteries
ROM:
8 MB
RAM:
4 MB
Requires optional V-Module that attaches to
PCMCIA:
Velo 1
Interfaces:
Serial port, Infrared port
continues
Previous | Table of Contents | Next
Table 3.7
Velo 1 Hardware Specifications, continued
Category
Audio:
Description
Built-in speaker and microphone
3 LEDs: alarm, battery charging,
Indicator LED:
communication
Built-in 19.2 modem; Two expansion
slots for DRAM, FLASH, or ROM; 10
Quick Start keys; Omni-directional
Additional Features:
microphone; Voice recording; Additional
application in ROM; CD-ROM of
additional applications
The following lists optional accessories available for the Phillips Velo 1:
Velo Dock
Traveling AC adapter
Flash memory
Type II PC card V-Module
NiMH rechargeable battery pack
Velo carrying case
Previous | Table of Contents | Next
CHAPTER 4
for writing applications for Windows CE. This includes cross-compilers, the
SDK and DDK, remote tools, remote debugging capabilities, and even an
emulation environment.
It is important to note that because Windows CE applications are built on a
desktop PC and Visual C++ for Windows CE includes an emulation
environment, it is completely possible to create Windows CE applications
without having a Handheld PC. Of course, at some point the application
should be tested on an actual Handheld PC.
This chapter will cover each of the components and tools used in building
Windows CE applications.
Development Environment
Currently the only way to get the SDK and tools needed for creating Windows
CE applications is with the Microsoft Visual C++ for Windows CE product.
This section provides information about what is included with the Visual C++
for Windows CE product, what is needed to use it, and how it is installed.
NOTE
The information in this chapter applies to version 1.0 of
Microsoft Visual C++ for Windows CE. Subsequent versions of
Visual C++ for Windows CE or Windows CE support for other
development environments differ somewhat from the information
provided here.
Installing Visual C++ for Windows CE
The installation of Visual C++ for Windows CE is very straightforward. The
major prerequisite is that Visual C++ 5.0 must first be installed on the system.
Other requirements for Visual C++ for Windows CE include:
A PC with a 486/66 MHz or higher processor
Page 53
Microsoft Windows NT Workstation 4.0
Microsoft Visual C++ 5.0, Professional or Enterprise edition
24 MB of RAM; 32 MB recommended
100 MB of free disk space
Because Visual C++ for Windows CE integrates directly into the Visual C++
development environment, it is very version specific. Visual C++ for Windows
CE version 1.0 will only work with Visual C++ 5.0, Professional or Enterprise
edition.
Although Microsoft strongly recommends Windows NT 4.0 as the operating
system platform, Visual C++ for Windows CE can be installed on Windows 95
with a few limitations. Some of the drawbacks of using Windows 95 are that
emulation, remote debugging, and remote tools will not work with Windows
95.
In addition to the Windows CE add-on for Visual C++, the Visual C++ for
14. The drop-down list should now contain the port that you have just
configured. Select the port, and click OK. On some builds of NT, the
drop-down list may not display the port that was just added. If it does
not, repeat steps 8-14. Eventually, NT will detect the modem.
15. In the Remote Access Setup dialog box, select the port that you have
just configured, and click Configure.
16. Select the Receive calls only radio button, and click OK.
17. In the Remote Access Setup dialog box, click Network.
18. In the Server Settings group, set the TCP/IP check box to TRUE. If you
have no other modem previously installed, make sure you clear the other
check boxes. Otherwise, leave the other check boxes as they are.
19. Click the Configure button for TCP/IP.
20. Select the This computer only radio button.
21. Select the Use static address pool radio button. For Begin, enter
192.168.55.100; for End, enter 192.168.55.112.
22. Make sure you clear the Allow remote clients to request a predetermined
IP address check box.
23. Continue by affirmatively exiting all the dialog boxes, clicking Close
when you reach the Network dialog box.
24. If a Microsoft TCP/IP Properties dialog box pops up, click OK.
25. Restart your computer when prompted.
Setting Permissions for a Guest Account
In order for Handheld PCs to connect to Windows NT, the guest user should
be enabled. When first connecting, the User Logon dialog box will appear on
the Handheld PC. Enter guest for User with no password or domain entries.
The following directions detail the steps for enabling the guest account:
Previous | Table of Contents | Next
Page 56
1. In Programs, Administrative Tools, start User Manager.
2. In the top box, double-click Guest.
3. Make sure that the Account Disabled check box is FALSE.
4. Click OK and close the User Manager dialog box.
5. In Programs, Administrative Tools, start Remote Access Admin.
6. Choose Users, Permissions.
7. In the Users list box, select Guest, and set the Grant dialing permission to user
check box to TRUE.
8. Click OK.
9. Select Server, Select Domain or Server.
10. In the Domain entry field, type your machine name (for example,
MYACCOUNT1).
11. Click OK.
Components of Visual C++ for
Windows CE
Installing Visual C++ for Windows CE produces almost no visual difference in the
Visual C++ integrated development environment (IDE). This keeps with Microsoft's goal
of maintaining a familiar environment for building Windows CE applications. About the
only interface change is the addition of new menu options specific to developing
Windows CE applications.
Although there are only minor interface changes, Visual C++ for Windows CE includes
many components. The components include:
Windows CE API (essentially a subset of the Win32 API set)
Windows CE C Runtime library (essentially a subset of the standard C Runtime
library)
Page 57
Windows CE Targets
Visual C++ for Windows CE uses the Visual C++ IDE's existing support for multiple
targets. Previous targets in the IDS included the Win32 Release and Win32 Debug.
Visual C++ for Windows CE enables the following new targets:
Win32 (WCE MIPS) Release
Win32 (WCE MIPS) Debug
Win32 (WCE SH) Release
Win32 (WCE SH) Debug
Win32 (WCE x86em) Release
Win32 (WCE x86em) Debug
MFC
Although not part of the early beta releases of the Windows CE SDK, Microsoft
Foundation Classes (MFC) support was added by the time the SDK was officially
released. The MFC support in Windows CE is a subset of the full MFC support for the
Win32 API.
Page 58
The addition of MFC greatly benefits the thousands of developers who have experience
in MFC programming. There are some drawbacks however. One important issue is that
the initial set of Handheld PCs do not have the MFC runtime DLLs in ROM. This means
that applications that need the MFC runtime library must install the DLL as part of their
installation.
Another related issue is the size of the MFC DLL. The debug MFC DLL has over 700K
for the SH3 processor and over 1 MB for the MIPS processor. This makes debugging
MFC applications next to impossible on a 2 MB Handheld PC. The release of MFC DLL
has 300K for the SH3 processor and 400K for the MIPS processor. While they certainly
fit on the Handheld PC, the DLL would take up a significant portion of the object store
on a 2 MB machine.
NOTE
CEditView
CMapWordToPtr
CSize
CArchiveException
CEvent
CMemoryException
CSliderCtrl
CArray
CException
CMenu
CSpinButtonCtrl
CBitmap
CFile
CNotSupportedException
CSplitterWnd
CBitmapButton
CFileDialog
CObArray
CStatic
Page 59
CBrush
CFileException
CObject
CString
CButton
CFileStatus
CObList
CStringArray
CByteArray
CFindReplaceDialog
CPaintDC
CStringList
CClientDC
CFont
CPen
CSyncObject
CCmdTarget
CFormView
CPoint
CTabCtrl
CCmdUI
CFrameWnd
CProgressCtrl
CTime
CComboBox
CGdiObject
CPropertyPage
CTimeSpan
CCommandLineInfo
CHeaderCtrl
CPropertySheet
CTreeCtrl
CCommon
Dialog
CImageList
CPtrArray
CTreeView
CPtrList
CTypedPtrArray
CCreateContext
CList
(template)
CCriticalSection
CListBox
CRecentFileList
CTypedPtrLis
CCtrlView
CListCtrl
CRect
CTypePtrMap
CDataExchange
CListView
CRectTracker
CUIntArray
CDC
CMap
(template)
CResourceException
CUserException
CDialog
CMapPtrToPtr
CRgn
CView
CDocTemplate
CDocument
CMapPtrToWord
CMapStringToOb
CRuntimeClas
CScrollBar
CWaitCursor
CWinApp
Page 60
CDumpContext
CMapStringToPtr
CDWordArray
CMapStringToString
CEdit
CMapWordToOb
CScrollView
CSingleDocTemplate
CSingleLock
CWindowDC
CWinThread
CWnd
CWordArray
this chapter. The Remote Debugging connection is configured from within Visual C++
with the Build, Debugger Remote Connection menu option.
The Debugger Remote Connection dialog box enables the debugging connection setting
to be specified for each target platform. Debugging Windows CE applications requires
configuring the Win32 (WCE MIPS) and Win32 (WCE SH) targets. Choose the Serial
connection method and then use the Settings dialog box to specify the connector port,
baud rate, and so on.
Previous | Table of Contents | Next
Page 63
Shell Emulation
A unique feature of Visual C++ for Windows CE is the capability to run
Windows CE applications on the desktop computer. The Windows CE
emulation environment makes it possible to build and test Windows CE
applications entirely under Windows NT.
The SDK provides a very faithful emulation of the Windows CE operating
system. Of course, performance and hardware specific features are not
emulated, so at some point testing is required on a physical Windows CE
device. According to Microsoft, approximately 90 percent of an application
development process can take place entirely in emulation. Figure 4.1 shows an
example of an application running under the emulation environment.
Figure 4.1
The Microsoft Windows CE emulation environment.
One component of the emulation environment is the object store. The object
store is contained in the file Wceobstr.dat. It contains the registry, databases,
and files. The tree structure is identical to the real object store on a Handheld
PC device; all semantics are the same. The root is "\", for example, and there is
no concept of a current directory. The application FILESYS.EXE is used to
manage the object store.
The other major component of the emulation environment is the shell. The
application SHELL32.EXE emulates the Handheld PC shell. The emulation
shell provides the same screen size and has the same look and feel as the real
Handheld PC shell.
Page 64
The emulation environment is started automatically when running or
debugging an application that has a target of x86EM. The emulation
environment can also be started directly by running SHELL32.EXE.
The Settings menu option on the Start menu in the emulation shell enables
some configuration of the emulation shell. Specifically, the screen size of the
emulation shell can be configured as well as the placement of the emulation
shell.
As stated in the preceding text, emulation provides an environment that is very
close to the actual Windows CE environment. However, there are small
interface differences as well as missing functionality from the emulation
environment. The visual appearance and size of tab controls, for example, can
be slightly different under emulation.
Areas that are not supported under emulation include:
2bpp bitmaps
Page 66
Remote Spy
Like the local desktop Spy++ application, Remote Spy is used to view the
messages that are being sent to a particular window. The Remote Spy runs on
the desktop PC but examines windows on the Handheld PC. Figure 4.3 shows
the interface for the Remote Spy tool.
Figure 4.3
The Remote Spy application.
The Remote Spy tool shows the hierarchy of windows that is created on the
Handheld PC and displays various window attributes for the window that is
selected. Clicking the Spy on Window button brings up another window,
which logs the messages that are sent to the selected window. Like the desktop
version, the tools can be configured to only display selective messages.
Much like the functionality of the desktop version for interactively finding a
window, clicking the Finder switch enables a window to be selected on the
Handheld PC using the stylus. Once a window is selected on the Handheld PC,
it is highlighted in the Remote Spy interface.
Remote Registry Editor
Although much of the system information for Windows CE is maintained in
the Windows CE registry, there is no end-user tool for directly manipulating
the registry (such as Regedit). Instead, the
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
Windows CE SDK include a desktop PC application that can manipulate the contents of a connected Handheld PC. Figure 4.4
shows the Remote Registry Editor.
The Remote Registry Editor has the same functionality as the local desktop Registry Editor. It enables keys and values to be
viewed, modified, and deleted. It also has a search mechanism for finding information in the registry.
Figure 4.4
The Remote Reg istry Editor appli cation.
An important difference in the Remote Registry Editor is that updating the registry is a two step process. A change made to the
registry is not reflected to the physical Handheld PC registry until it is "exported." Selecting the Export Registry menu option
copies any registry changes to the Handheld PC device.
Note that the following characters cannot be used in values that are exported to the Handheld PC device:
0x005e (`^') 0x007e (`~') 0x003d (`=') 0x0022 (`"`)
Page 68
Remote Zoomin
Remote Zoomin is the counterpart to the Win32 SDK Zoomin application. Remote Zoomin captures a portion of the Handheld
PC screen. Figure 4.5 shows the Remote Zoomin tool with a full screen captured.
Figure 4.5
The Remote Zoomin application.
In addition to zooming in to a portion of the Handheld PC screen, the Zoomin tool is also very convenient for doing a screen
capture of the entire Handheld PC screen. The Get Full HPC Screen menu option captures the entire Handheld PC screen.
You can capture a smaller portion of the Handheld PC screen by selecting the Define HPC Zoom Area menu option and then
drawing a rectangle with the stylus directly on the Handheld PC screen.
The Refresh HPC Zoom Area menu option refreshes the Remote Zoomin window with the current contents of the Handheld
PC screen (for the previously set zoom area).
You can increase or decrease the magnification of the image in the Remote Zoomin window by using the scrollbar on the right
side of the window.
Page 69
Remote Object Viewer
The Remote Object Viewer application is a tool that can view and manipulate a Windows CE object store. The object store can
be on a remote Handheld PC, or the object store that is created for the emulation environment. Figure 4.6 shows the Remote
Object Viewer interface.
Figure 4.6
The Remote Object Viewer application.
The Remote Object Viewer's tree displays a variety of objects that includes the following:
Handheld PC Database. This node contains all of the databases on the Handheld PC. When a database is selected, the
right pane displays that database's records.
Handheld PC Files. This node contains the directories and files in the Handheld PC object store. When a directory is
selected, the right pane displays the directory's files and subdirectories.
C: Drive. This is the desktop machine's boot drive. This node is present to allow copying and moving of files between
the desktop PC and the Handheld PC.
Emulator Database. This node contains all of the databases in the emulation environment. When a database is selected,
the right pane displays that database's records.
Emulator Files. This node contains the directories and files in the emulation environment object store. When a directory
is selected, the right pane displays the directory's files and subdirectories.
Page 70
An important feature of the Remote Object Viewer is the capability to copy information between the Handheld PC object store
and the emulation environment object store. This makes it easy to put information in the object store under the emulation
environment. This is done in order to debug or test an application under emulation that requires information from the object
store.
Another feature of the Remote Object Viewer is the capability to directly edit database records. Double-clicking a record in the
right pane displays a properties window that shows the record's properties and values. The values can be changed by
double-clicking a particular property.
Remote Memory Viewer
The last and most complex tool included in the Windows CE SDK is the Remote Memory Viewer. Contrary to its name, this
tool does a lot more than examine memory on the Handheld PC. Figure 4.7 shows the WCE Remote Memory Viewer.
Figure 4.7
The Remote Memory Viewer application.>
The Remote Memory Viewer tool can be used to examine many aspects of the Windows CE memory architecture as presented
in Chapter 1. Some of the information displayed in the Remote Memory Viewer
Page 71
deals with the low-level Windows CE kernel implementation and is beyond the scope of this book. This section will detail the
information presented in the Remote Memory Viewer, but not necessarily attempt to explain exactly what it means.
The Remote Memory Viewer is divided into three panes. The top pane displays information about the processes currently
running on the Handheld PC. The following columns of the top pane detail information about the process:
3
4
5
Description
Thread is either running or will
Runable
run when time sliced.
Thread is waiting for time to
Sleeping
pass (e.g.: called Sleep).
Thread Section Block has
Critical
blocked on a call to
EnterCriticalSection.
Thread has blocked on a call to
Event Blocked WaitForSingleObject with an
event handle.
Suspended
Thread is suspended.
Terminated
Thread has terminated.
The bottom pane of the Remote Memory Viewer application lists information
about the current modules (DLLs) that are loaded. The columns of this pane
include the following:
Module Name. The name of the module.
In-use flags. Indicates which processes are using the DLL.
Handle. The handle to the module.
Base Ptr. The DLL's base pointer (starting point in memory).
Start IP. The DLL's entry point (address of DllMain).
Double-clicking a process name in the top pane brings up the Process Memory
Map dialog box (see Figure 4.8). The memory map shows the pages that are
currently allocated to the process and details each page's type. The possible
page types include the following:
S: Stack page
A final set of information that can be retrieved with the Remote Memory
Viewer is a summary of the resources currently used by the Windows CE
kernel. Figure 4.9 shows the Kernel Summary dialog box that is displayed by
choosing the View, Kernel Summary menu option.
Figure 4.9
The Kernel Sum mary dialog box.
Page 74
Previous | Table of Contents | Next
CHAPTER 5
Hello Windows CE
Carrying on the tradition of a "Hello World" program and a "Hello Windows" program, this chapter presents an analogous
program written for Windows CE. This program will show the basic components needed for a Windows CE application.
Because the API for Windows CE is really just a subset of Win32, the "Hello Window CE" program will look very much
like a "Hello Windows" program written for Win32. However, there are some obviousand some subtledifferences.
These differences will be explored in detail in this chapter.
Even though much of the code will be identical to a simple Win32 program, these initial steps are examined in detail. Even
for the experienced Win32 programmer, some of these steps may be unfamiliar, due to the widespread use of aids like
Microsoft Foundation Class (MFC) and Borland's Object Windows Library.
Another benefit of these class libraries is that they implement most of the infrastructure that is needed to use C++ to
develop a Windows application. Because the Windows API is primarily designed for C, there are some programming
challenges to overcome in order to use C++ to build an application.
Page 76
Note
During the final stages of this book, MFC support was added for Windows CE development. MFC support for
Windows CE is a subset of the full MFC library and has some implications due to the size of the runtime
components with the limited storage size available on Handheld PCs.
To begin exploring programming for Windows CE, Hello Windows CE will first be implemented in straight C. This creates
a small sample that will make it easier to explore the fundamentals of a Windows CE application.
After examining the components of the application, the sample will be redone in C++. This entails adding the infrastructure
described in the preceding text to make building a Windows CE application in C++ easier. Because this infrastructure is
easily reusable, the remaining chapters of the book will use C++. Additionally, C++ also makes it simple for you to reuse
any of the code presented in this book.
UINT msg,
WPARAM
wParam
LPARAM lParam )
Page 77
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
HWND wndCB;
switch (msg)
{
case WM_CREATE:
wndCB = CommandBar_Create(hInst, hWnd, 1);
CommandBar_AddAdornments(wndCB, 0, NULL);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rect);
DrawText(hdc, TEXT("Hello Windows CE"), -1, &rect,
DT_SINGLELINE|DT_CENTER
|DT_VCENTER);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wParam, lParam));
}
return (0);
}
BOOL RegisterWindowClass()
{
WNDCLASSW
wc;
wc.style
wc.lpfnWndProc
wc.cbClsExtra
wc.cbWndExtra
=
0 ;
= (WNDPROC) WndProc;
= 0;
= 0;
Page 78
wc.hInstance
= hInst;
wc.hIcon
= NULL;
wc.hCursor
= NULL;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName
= NULL;
wc.lpszClassName = szClassName;
return RegisterClass(&wc);
}
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
return(TRUE);
}
int WINAPI WinMain ( HINSTANCE hInstance,
HINSTANCE
hPrevInstance,
LPWSTR
lpCmdLine,
int
nCmdShow )
{
MSG msg;
// Is there another instance already running
if ( hPrevInstance != 0 )
{
return FALSE;
}
// Set the global instance handle
hInst = hInstance;
if ( RegisterWindowClass() == FALSE )
{
return(FALSE);
}
// API call to initialize common controls
InitCommonControls();
if ( CreateMainWindow(nCmdShow) == FALSE )
{
return(FALSE);
}
// Main window was created, start the message loop
while ( GetMessage(&msg, NULL, 0, 0) != FALSE )
{
Page 80
TranslateMessage (&msg) ;
DispatchMessage(&msg);
}
return(msg.wParam);
}
Note
All of the source code presented here can also be found on the accompanying CD-ROM. See Appendix A,
"Getting Started with the CD-ROM," for details on the contents of the CD-ROM and for information on
accessing the example code.
Once the HELLO sample is built and executed (either in emulation mode, or by downloading it to the Handheld PC and
running it), the program creates a normal application window (as shown in Figure 5.1).
Figure 5.1
HELLO applica tion.
HINSTANCE
LPWSTR
int
Keyword
Brief
Full
Advanced
Search
Search Tips
The following code demonstrates how to register a window class in Windows CE:
WNDCLASS
wc;
wc.style
=
0 ;
wc.lpfnWndProc
= (WNDPROC) WndProc;
wc.cbClsExtra
= 0;
wc.cbWndExtra
= 0;
wc.hInstance
= hInst;
wc.hIcon
= NULL;
wc.hCursor
= NULL;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName
= NULL;
wc.lpszClassName = szClassName;
RegisterClass(&wc);
The members of the WNDCLASS structure are as follows:
style. Specifies the class style. Windows CE supports only one style, so this parameter must be NULL.
lpfnWndProc. Points to the window procedure that will process the messages sent to this class of window.
cbClsExtra. Specifies the number of extra bytes to allocate following the window-class structure. The
operating system initializes the bytes to zero.
cbWndExtra. Specifies the number of extra bytes to allocate following the window instance. The operating
system initializes the bytes to zero.
hInstance. Identifies the instance that the window procedure of this class is within.
hIcon. Identifies the class icon. This member must be a handle of an icon resource. If this member is
NULL, an application must draw an icon whenever the user minimizes the application's window.
Page 83
hCursor. There is no cursor in Windows CE, so this parameter must be NULL.
hbrBackground. Identifies the class background brush.
lpszMenuName. Windows CE does not support default menus, so this parameter must be NULL.
lpszClassName. Points to a null-terminated string that specifies the window class name.
Once all the members of the WNDCLASS structure have been initialized, the structure is passed to the
RegisterClass function. Each window class only needs registered once, regardless of the number of windows
created with that class. That is, the window class defines the general characteristics of a window, thus allowing
many different windows to be created under the same window class.
Creating the Main Window
After registering the window class, the actual window can be created with the CreateWindowEx function.
hWnd = CreateWindowEx(0,
// extended styles
szClassName,
// class name
szTitle,
// window title
WS_VISIBLE,
// styles
0,
// x position
0,
// y position
CW_USEDEFAULT,
// width
CW_USEDEFAULT,
// height
NULL,
// parent
NULL,
Page 84
// menu
hInst,
// instance handle
NULL);
// user data
Note
There is also a CreateWindow function with all the same parameters as CreateWindowEx except
the first extended style parameter.
The CreateWindowEx function specifies the details of the window's appearance and functionality. The
parameters for CreateWindowEx are the same as Win32 with the following exceptions:
dwExStyle. The only supported flags are the following:
WS_EX_WINDOWEDGE
WS_EX_CLIENTEDGE
WS_EX_STATICEDGE
WS_EX_OVERLAPPEDWINDOW
dwStyle. The only supported flags are the following:
WS_BORDER
WS_CAPTION
WS_CHILD
WS_CLIPSIBLINGS
WS_CLIPCHILDREN
WS_DISABLED
WS_DLGFRAME
WS_GROUP
WS_HSCROLL
Page 85
WS_OVERLAPPED
WS_TILED
WS_POPUP
WS_TABSTOP
WS_SYSMENUWindows CE does not have a system menu, but this flag is used to determine
whether the window's title bar should have accessories such as widgets-buttons, OK, ?, and so on.
WS_VISIBLE
WS_VSCROLL
The following list includes other facts exclusive to CreateWindowEx:
WS_CLIPSIBLINGS and WS_CLIPCHILDREN. All windows are implicitly these two style bits.
Owner windows. These are not supported.
LBS_OWNERDRAWFIXED and LBS_OWNERDRAWVARIABLE. These list box styles are not
supported.
CBS_OWNERDRAWFIXED and CBS_OWNERDRAWVARIABLE. These combo box styles are not
supported.
hwndParent. If this is not NULL, the window is implicitly given the WS_CHILD style bit.
Menu bars. These are not supported.
SS_SIMPLE. This is not supported for static controls. You may use SS_LEFT or
SS_LEFTNOWORDWRAP as a work-around.
hMenu. It must be NULL, unless it is used as a child-window identifier.
Page 86
Owned dialogs. These are the only dialogs that are supported. They are created via the Dialog Manager
API's.
MDICLIENT. This is not supported.
The return value from CreateWindowEx is the handle to the newly created window. Once the window is created,
it is displayed using the following code:
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
The ShowWindow function sets the specified window's show state. Windows CE only supports the following
states:
SW_HIDE
SW_SHOW
SW_SHOWNA
SW_SHOWNOACTIVATE
SW_SHOWNORMAL
The UpdateWindow function updates the client area of the specified window by sending a WM_PAINT message
to the window procedure of the specified window.
The Message Loop
After the UpdateWindow function call, the window is fully visible. As with all Windows programs, it is now
necessary to create a "message loop." This loop will retrieve messages from the message queue and process them.
The message loop is demonstrated in the following code:
UINT msg,
WPARAM
wPara
LPARAM lParam )
The syntax and parameters of the window procedure are identical to window procedures under Win32.
Messages
Each message procedure that a window procedure receives is identified by a number that is specified in the msg
parameter. The message numbers are defined in header files that are part of the Software Development Kit
(SDK).
An application generally uses a switch statement to look for and process the messages it is interested in. The
Hello sample handles three messages: WM_CREATE, WM_PAINT, and WM_DESTROY.
The WM_CREATE Message
Once a window has been created but before it is visible, the window receives a WM_CREATE message. This
message is identical to the WM_CREATE message under Win32. The LParam parameter points to a
CREATESTRUCT that contains information about the window
Previous | Table of Contents | Next
end of painting in the specified window. The BeginPaint and EndPaint functions operate the same under
Windows CE as they do under Win32.
As in Win32, the GetClientRect function retrieves the dimensions of the client area of the window.
Note
The GetClientRect does not account for the command bar in the client area. This detail will be
covered in the next chapter.
The DrawText function is used to draw text. The parameters tell it what text to draw, where to draw it, and
how to draw it. There is no change in this function for Windows CE.
The WM_DESTROY Message
As with other Windows platforms, the WM_DESTROY message indicates that Windows is in the process of
destroying a window based on a command from the user. This message could result from the user tapping on
the Close button or pressing Alt+F4. The HELLO sample handles the WM_DESTROY message by calling
the PostQuitMessage function to end the program.
case WM_DESTROY:
PostQuitMessage(0);
break;
In response to a WM_DESTROY message, the HELLO sample calls the PostQuitMessage function. This
function inserts a WM_QUIT message in the program's message queue. The WM_QUIT message is the one
message that will cause the GetMessage function in the message loop to return FALSE. This causes
WinMain to drop out of the message loop and exit, terminating the program.
Page 90
Moving to C++
Anyone familiar with MFC or OWL knows that writing a "Hello Windows" program takes a lot less code
than the sample has used. That's because MFC and OWL have a lot of their own code to implement some of
the basic components the HELLO sample needed. The goal in this instance is not to duplicate those big class
libraries, but to do enough to allow you to group some code in C++ classes.
Every Windows application, including Windows CE applications, needs a WinMain. Therefore, WinMain is
one C-style function that can't go away. The other big hurdle is the WndProc function. When using MFC, it's
rare to use a true WndProc window procedure, but WndProcs already are buried in MFC code. Instead,
messages end up in the OnCommand method for the given window class (C++ class, not WNDCLASS
class). MFC does the necessary work to get the message from its WndProc to the OnCommand method for
the right object.
The following "Hello++ Windows CE" sample implements a simple strategy for using C++ under Windows
CE. MFC goes way beyond this strategy; for example, message maps go beyond the scope of this book.
Page 91
Now that MFC is available for Windows CE development, it may be very useful for some application
development. This book uses straight API calls and not MFC, however, in order to focus on the differences
between Win32 programming and Windows CE programming.
The HELLO++ Sample
The HELLO++ application has the same functionality as the HELLO application, except that it uses C++ to
group some parts together. The sample uses two classes: an application class and a main window class, as
shown in the following code.
#include <windows.h>
// Class name and window title
WCHAR szClassName[] = TEXT("Helloxx");
WCHAR szTitle[] = TEXT("Hello++ Windows CE Application");
// The application class
class HelloApp
{
public:
HelloApp();
~HelloApp(){}
BOOL Create(HINSTANCE);
int Run();
HINSTANCE m_hInst;
};
// The main window class
class MainWindow
{
public:
MainWindow() {}
~MainWindow() {}
BOOL Create(HelloApp *);
void WMCreate(HWND);
void WMPaint();
Page 92
private:
HWND m_hWnd;
HelloApp * m_pApp;
};
// Global Window handle
MainWindow * g_pMainWindow = NULL;
// Implementation of MainWindow methods
void MainWindow::WMCreate(HWND hWnd)
{
HWND wndCB = CommandBar_Create(m_pApp->m_hInst, hWnd, 1);
CommandBar_AddAdornments(wndCB, 0, NULL);
}
void MainWindow::WMPaint()
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
hdc = BeginPaint(m_hWnd, &ps);
GetClientRect(m_hWnd, &rect);
DrawText(hdc, TEXT("Hello Windows CE"), -1, &rect,
DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(m_hWnd, &ps);
}
BOOL MainWindow::Create(HelloApp * pHelloApp)
{
m_pApp = pHelloApp;
g_pMainWindow = this;
m_hWnd = CreateWindowEx(0,
// extended styles
szClassName,
// class name
szTitle,
// window title
WS_VISIBLE,
// styles
0,
Keyword
Brief
Full
Advanced
Search
Search Tips
// x position
0,
// y position
CW_USEDEFAULT,
// width
CW_USEDEFAULT,
// height
NULL,
// parent
NULL,
// menu
m_pApp>m_hInst,
// instance handle
NULL);
// user data
UINT msg,
WPARAM
case WM_CREATE:
g_pMainWindow->WMCreate(hWnd);
break;
case WM_PAINT:
g_pMainWindow->WMPaint();
break;
Page 94
case WM_DESTROY:
delete g_pMainWindow;
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wParam, lParam));
}
return (0);
}
// Implementation of HelloApp methods
HelloApp::HelloApp()
{
// API call to initialize common controls
InitCommonControls();
}
BOOL HelloApp::Create(HINSTANCE hInstance)
{
WNDCLASS
wc;
m_hInst = hInstance;
wc.style
=
0 ;
wc.lpfnWndProc
= (WNDPROC) WndProc;
wc.cbClsExtra
= 0;
wc.cbWndExtra
= 0;
wc.hInstance
= m_hInst;
wc.hIcon
= NULL;
wc.hCursor
= NULL;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName
= NULL;
wc.lpszClassName = szClassName;
if ( !RegisterClass(&wc) )
{
return FALSE;
}
// RegisterClass worked, so create the window
MainWindow * pMainWindow = new MainWindow();
Page 95
if ( !pMainWindow )
{
return FALSE;
}
if ( !pMainWindow->Create(this) )
{
return FALSE;
}
return TRUE;
}
int HelloApp::Run()
{
MSG msg;
// Main window was created, start the message loop
while ( GetMessage(&msg, NULL, 0, 0) != FALSE )
{
TranslateMessage (&msg) ;
DispatchMessage(&msg);
}
return(msg.wParam);
}
int WINAPI WinMain ( HINSTANCE hInstance,
HINSTANCE
hPrevInstance,
LPWSTR lpCmdLine,
int nCmdShow )
{
// Is there another instance already running
if ( hPrevInstance != 0 )
{
return -1;
}
HelloApp * pApp = new HelloApp();
if ( !pApp )
{
Page 96
return -1;
}
if ( pApp->Create(hInstance) == FALSE )
{
return -1;
}
BOOL exitVal = pApp->Run();
delete pApp;
return exitVal;
}
The HelloApp Class
The first class in the HELLO++ application is the HelloApp class. This is the application class that comprises most of
CHAPTER 6
Source code for the TravelManager application can also be found on the accompanying CD-ROM. See
Appendix A, "Getting Started with the CD-ROM," for information on installing and building the example
code on the CD-ROM.
Page 101
Working with Command Bars
The first interface component to add to the application is the command bar. Under Windows 95 and
Windows NT, the title bar, menu bar, and toolbar are each given a row of space in the window. However,
because real estate is such a premium on Windows CE and because applications rarely fill the entire width
of the window with menu items or toolbar buttons, Windows CE combines all those elements into a single
space known as the command bar. The command bar is located at the top of each window. Four example
command bars are shown in Figure 6.1, while the TravelManager's command bar is shown in Figure 6.2.
Figure 6.1
Example command bars.
Figure 6.2
The TravelManager application's command bars.
Before examining the code used to create the TravelManager's command bar, the parts of the command bar
must be identified. The first box in the command bar is the menu bar, consisting of the menus File, Edit,
View, and Help. After the menu bar is a combo box, which is used by TravelManager as a quick navigation
tool. Following the combo box is a number of buttons. The first seven buttons are the TravelManager's
buttonbar. The last two buttons, Help and Close, are common to most Windows CE applications.
A command bar can include four different types of elements: menu bars, buttons, combo boxes, and
separators. A separator divides items into groups by adding space between them.
Page 102
The position of each element in the command bar is identified by a zero-based index value, with the
leftmost item at position zero. This index position is often used to identify where to insert an element into
the command bar. The new element is inserted to the left of the specified index position. To insert an
element to the right of the current rightmost element, specify an index one greater than the index of that
element.
Before adding any control, the command bar must first be created using the CommandBar_Create function.
The TravelManager application does this in the new CreateCommandBar method of the MainWindow
class.
HWND hwndCB = CommandBar_Create(m_pApp->m_hInst, m_hWnd, ID_COMMANDBAR);
The CommandBar_Create parameters are as follows:
HINSTANCE. Specifies the application instance in which the command bar is to be created.
Other factors you should consider pertaining to the CommandBar_Create are as follows:
The return value is a handle to the newly created command bar.
Windows CE automatically sets the size of the command bar and positions the bar along the
top of the parent window's client area.
Because command bars are optional, Windows CE does not automatically account for them when retrieving
the client area using the GetClientRect function. To determine the useable portion of the client area, adjust
the rect returned from GetClientRect with the height of the command bar. The height of the command bar
can be found using the CommandBar_Height function.
Page 103
Creating Menu Bars
Inserting and formatting menus in Windows CE is similar to inserting and formatting menus in Win32. The
CommandBar_InsertMenubar function is used to insert a menu bar into a command bar.
CommandBar_InsertMenubar(hwndCB, m_pApp->m_hInst, IDM_MAIN_MENU, 0);
The CommandBar_InsertMenubar parameters are as follows:
HWND. Specifies the handle of the command bar in which to insert the menu bar.
HINSTANCE. Specifies the application instance from which to get the menu resource.
int. Specifies the zero-based index of a command bar element. The function inserts the menu bar to
the left of this element. Menus are usually started at position zero.
The menu resource format under Windows CE remains unchanged from Win32. The trvlmgr.rc file
specifies the menu resource for the TravelManager application:
IDM_MAIN_MENU MENU DISCARDABLE
BEGIN
POPUP "File"
BEGIN
MENUITEM "Save",
MENUITEM SEPARATOR
MENUITEM "Exit",
END
POPUP "Edit"
BEGIN
MENUITEM "Cut",
MENUITEM "Copy",
MENUITEM "Paste",
END
POPUP "View"
ID_FILE_SAVE
ID_FILE_EXIT
ID_EDIT_CUT
ID_EDIT_COPY
ID_EDIT_PASTE
Keyword
Brief
Full
Advanced
Search
Search Tips
BEGIN
MENUITEM
MENUITEM
MENUITEM
END
POPUP "Help"
BEGIN
MENUITEM
MENUITEM
MENUITEM
END
"Itinerary",
"Expenses",
"Notes",
ID_VIEW_ITINERARY
ID_VIEW_EXPENSES
ID_VIEW_NOTES
"Contents",
SEPARATOR
"About",
ID_HELP_CONTENTS
ID_HELP_ABOUT
The menu resource specifies the structure of the menus, the label for each menu, and the ID number that
Windows CE sends to the application (in a WM_COMMAND message) when the user chooses that menu item.
The ID numbers for the TravelManager are defined in the resource.h file. The menu resource files and the code
can be found on the accompanying CD-ROM.
After inserting a menu bar into the command bar, the Win32 menu API functions can be used to manage the
menu. To retrieve a handle
to the menu bar, use the CommandBar_GetMenu function. After creating
the menu bar, the TravelManager application adds a check mark to the Itinerary menu item of the View menu
(because this is the default view that is created). This can be referenced by noticing the following code:
HMENU hMenu = CommandBar_GetMenu(hwndCB,0)
CheckMenuItem(hMenu, ID_VIEW_ITINERARY, MF_CHECKED);
One difference from Win32 menus is that cascading (sometimes called hierarchical) menus are not currently
supported by Windows CE. As an alternative to cascading menus, you can increase the number of menu
commands or display further choices in a dialog box.
Creating Combo Boxes
Under Win32, adding a combo box to a toolbar was not an easy task. Luckily, under Windows CE it is much
simpler to add a combo box to the command bar. By using the CommandBar_InsertComboBox function, you can
easily create a combo box and insert it into a command bar.
Page 105
CommandBar_InsertComboBox(hwndCB, m_pApp->m_hInst, COMBOWIDTH,
CBS_DROPDOWNLIST | WS_VSCROLL, ID_COMBO,
COMBOPOSITION);
Note
Currently, only the CBS_DROPDOWNLIST and WS_VSCROLL styles are supported. The
WS_HASSTRINGS, WS_VISIBLE, and WS_CHILD styles are included automatically.
int. Specifies the zero-based index of a button. (The new combo box is inserted to the left of this button.)
After creating a combo box in Windows CE, an application can use the Win32 combo box API functions to add
items and manage the combo box. The TravelManager application uses a combo box in the command bar to
identify the available display options. TravelManager adds the display names to the combo box and selects the
first string as demonstrated in the following:
if (m_hwndCombo)
{
SendMessage(m_hwndCombo,
SendMessage(m_hwndCombo,
SendMessage(m_hwndCombo,
SendMessage(m_hwndCombo,
SendMessage(m_hwndCombo,
CB_ADDSTRING,
CB_ADDSTRING,
CB_ADDSTRING,
CB_ADDSTRING,
CB_ADDSTRING,
0,
0,
0,
0,
0,
(LPARAM)L"Airline");
(LPARAM)L"Car Rental");
(LPARAM)L"Hotel");
(LPARAM)L"Expenses");
(LPARAM)L"Notes");
Page 106
Creating Command Bar Buttons
The functionality of a Win32 toolbar is achieved in Windows CE by adding buttons to the command bar. The
buttons are added to the command bar by using the CommandBar_AddButtons function.
CommandBar_AddButtons(hwndCB, sizeof(tbButton)/sizeof(TBBUTTON),
tbButton);
The CommandBar_AddButtons parameters are as follows:
HWND. Specifies the handle of the command bar to which you want to add the buttons.
LPTBBUTTON. Points to an array of TBBUTTON structures that contains information about the buttons
to add. (The same number of elements must be in the array as buttons specified by the second parameter.)
int. Specifies the index of a button; the new button is added to the left of it.
LPTBBUTTON. Points to a single TBBUTTON structure that contains information about the button to
add.
Button attributes include the image and string displayed in the button, the button state and styles, and the button
command identifier. The members of the TBBUTTON structure are as follows:
int iBitmap. Specifies the zero-based index of the image for the button. (When using bitmaps that are
provided with the common control library, use the STD_ and VIEW_ constants in this member.)
Page 107
int idCommand. Specifies the command identifier for the button. This identifier is used in a
WM_COMMAND message when the button is chosen. (For separators, this member must be zero.)
BYTE fsState. Specifies the button state flags. This member can be any combination of the following
values:
TBSTATE_CHECKEDThe button has the TBSTYLE_CHECKED style and is being pressed.
TBSTATE_ENABLEDThe button accepts user input. A button that does not have this state does not
accept user input and is grayed.
TBSTATE_HIDDENThe button is not visible and cannot receive user input.
TBSTATE_PRESSEDThe button is being pressed.
TBSTATE_WRAPA line break follows the button. The button must also have the TBSTATE_ENABLED
state.
Page 108
DWORD dwData. Specifies application-defined data.
int iString. Specifies the zero-base index of the string for the button.
The TravelManager application creates a set of buttons using the following TBBUTTON array:
static TBBUTTON tbButton[] = {
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP,
0, 0, 0, _1},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP,
0, 0, 0, _1},
{STD_FILESAVE, ID_FILE_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, _1},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP,
0, 0, 0, 0},
{STD_CUT, ID_EDIT_CUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, 0},
{STD_COPY, ID_EDIT_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, _1},
{STD_PASTE, ID_EDIT_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0, _1},
{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP,
0, 0, 0, 0},
{15, ID_VIEW_ITINERARY, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0, _1},
{16,ID_VIEW_EXPENSES,TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0, _1},
{17,ID_VIEW_NOTES,TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0, _1},
{0,0, TBSTATE_ENABLED, TBSTYLE_SEP,
0, 0, 0, 0},
};
Button Images
Each button in the command bar can include a bitmapped image. The command bar stores the images for all
buttons in an internal image list. Initially, this image list is empty. However, you can add images to the list by
using the CommandBar_AddBitmap function.
CommandBar_AddBitmap(hwndCB,
0, 0);
CommandBar_AddBitmap(hwndCB,
CommandBar_AddBitmap(hwndCB,
CommandBar_AddBitmap(hwndCB,
HINSTANCE. Specifies the application instance that contains the bitmap resource.
HINST_COMMCTRL can be used to add the system-defined button bitmaps.
int. Specifies the bitmap resource that contains the button images. If HINSTANCE is
NULL, this parameter must be a handle to a bitmap that contains the button images.
A bitmap can consist of more than one image, but the dimensions of each individual image in the
bitmap should only be 1616 pixels. The system assumes all the images in the bitmap are the
same size. The first call to the CommandBar_AddBitmap function of the previous code sample
adds a bitmap that consists of 15 images, therefore the whole bitmap has a height of 16 pixels
and a width of 240 pixels (1615).
Each image has a zero-based index in the list. The first image added to the internal list has an
index of zero, the second has an index of one, and so on. CommandBar_AddBitmap adds images
to the end of the list and returns the index of the first new image that was just added. This index
is used to associate the image with a button.
The TravelManager application first adds a set of predefined button images that are part of
Windows CE. The HINSTANCE HINST_COMMCTRL is used as the instance handle, and
IDB_VIEW_SMALL_COLOR is used as the resource identifier. This resource includes the
common images that are associated with buttons such as Fileopen, Cut, Copy, Paste, and so on.
Another predefined set of images is the IDB_VIEW_SMALL_COLOR resource, which includes
images associated with views (list, detail, large icon, and so on.).
Page 110
The system header files include constants that define the indices for the predefined images. The
constants defined are as follows:
STD_COPY
STD_PROPERTIES STD_CUT
STD_REDOW
STD_DELETE
STD_REPLACE
STD_FIND
STD_PASTE
STD_FILENEW
STD_PRINT
STD_FILEOPEN
STD_PRINTPRE
STD_FILESAVE STD_UNDO
STD_HELP
VIEW_DETAILS VIEW_SORTDATE VIEW_LARGEICONS
VIEW_LIST
VIEW_SORTNAME VIEW_SORTSIZE
VIEW_SORTTYPE VIEW_SMALLICONS
After adding the set of 15 predefined buttons from the IDB_STD_SMALL_COLOR resource,
the TravelManager code adds three more application defined images. These images are the
resources IDB_ITINERAR, IDB_EXPENSES, and IDB_NOTES. These identifiers are defined
in resource.h and trvlmgr.rc.
IDB_ITINERAR
IDB_EXPENSES
IDB_NOTES
BITMAP
BITMAP
BITMAP
DISCARDABLE
DISCARDABLE
DISCARDABLE
"itinerar.2bp"
"expenses.2bp"
"notes.2bp"
Tip
As in Win32, these lines associate a resource identifier with a bitmap file. Because
these bitmaps hold only one image, the size of each bitmap is 1616 pixels.
Button Strings
In addition to or instead of an image, a button can also display a text string. As with images, a
command bar maintains an internal list that contains all strings available to buttons; these strings
are added to the
Page 111
internal list by sending the command bar a TB_ADDSTRING message. The TB_ADDSTRING
message specifies the address of the buffer that contains the strings to add. Each string must be
null-terminated, and the last string must be terminated with two null characters.
As with images, each string has a zero-based index and that index is used in the TBBUTON
structure to specify the position of the string in the list for each button.
Although not used in the TravelManager application, an example of adding strings to the internal
command bar list follows:
SendMessage(hwndCB, TB_ADDSTRING, (WPARAM)hInst,
MAKELONG(IDS_NEW, 0));
SendMessage(hwndCB, TB_ADDSTRING, (WPARAM)hInst,
MAKELONG(IDS_OPEN, 0));
After adding strings to the command bar's internal string list, a string can be associated with a
button by the iString member of the TBBUTTON structure. The iString member is set to the
desired string's index in the internal list.
Button States and Styles
Each button in a command bar has a current state. The command bar updates the button state to
reflect user actions, such as tapping the button. The state indicates whether the button is currently
pressed or not pressed, enabled or disabled, or hidden or visible. An application sets the initial
button state in the TBBUTTON structure when adding the button to the command bar. The state
of a button can be set using the TB_SETSTATE message, and the application can retrieve the
state of a button using the TB_GETSTATE message.
The TravelManager application creates a group of three buttons that have the
TBSTYLE_CHECKGROUP style. This style creates a set of buttons that toggles between
pressed and nonpressed states. Pressing one of the buttons in the group causes the others to be
"not-pressed."
Page 112
The TravelManager uses this button configuration to show which view is currently displayed so
that only one of the views can be displayed at one time.
SendMessage(hwndCB, TB_SETSTATE, (WPARAM)ID_VIEW_ITINERARY,
MAKELONG(TBSTATE_ENABLED|TBSTATE_CHECKED,0));
Tooltips
A tooltip control is a small window that displays help text. In Win32 applications, the tooltip is
displayed when the mouse is positioned over a button on the toolbar. Since there is no mouse in
Windows CE, the activation of the tooltip is a bit different. Using the stylus to press and hold
down a button on the command bar will display the tooltip.
Warning
If the stylus is moved off of the button before it is released, no button press event is
generated.
Under Win32, when a tooltip becomes activated over a toolbar, the tooltip control sends a
request to the application for the text to be displayed. Just as Windows CE has made the
displaying of combo boxes much simpler, displaying tooltips is also easier. The tooltip text for
the all the command bar buttons can be set when the command bar is created. The
CommandBar_AddToolTips function adds tooltips strings to the command bar:
static TCHAR * tooltips[] = {
L"",
L"",
L"Cut",
L"Copy",
L"Paste",
L"Itinerary",
L"Expenses",
L"Notes",
L"Help",
L"Exit"
};
CommandBar_AddToolTips(m_hwndCB, 10, tooltips);
Keyword
Brief
Full
Advanced
Search
Search Tips
The preceding code added the tooltip strings for all command bar buttons for TravelManager's
command bar. Although menus and combo boxes cannot display tooltip help, they must be
accounted for in the array of tooltip strings. In the TravelManager application, the menu and combo
box occupy the first two positions on the command bar. The tooltips array accounts for this by
specifying empty strings as the first two strings in the array.
Other Command Bar Functions
Just as Win32 applications usually have minimize, maximize, and close buttons, Windows CE also
supports some standard window adornments, such as close and help buttons. These buttons are
added with the CommandBar_AddAdornments function:
CommandBar_AddAdornments(m_hwndCB, CMDBAR_HELP, NULL);
The CommandBar_AddAdornments parameters are as follows:
HWND. Specifies the handle of the command bar window.
Element
Menu
Button
Combobox combo id
HIWORD
(wParam)
0
0
notification code
lParam
0
0
combo
window
handle
As you can see, messages from menus and command bar buttons look identical. This is quite useful
because command bar buttons almost always have a corresponding menu item. Because the
message is identical, the same code can be used to perform an action regardless of whether the user
presses the command bar button or choose the menu option.
The following snippet of code shows how the TravelManager application responds to command bar
messages. See the end of the chapter for the complete code listing.
LRESULT MainWindow::WMCommand( HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam )
{
WORD notifyCode = HIWORD(wParam);
if ( notifyCode == 0) // from menu?
{
switch (LOWORD(wParam)) // which menu item
{
case ID_HELP_ABOUT:
// display About box
break;
Page 115
case ID_VIEW_ITINERARY:
case ID_VIEW_EXPENSES:
case ID_VIEW_NOTES:
// handle view change
break;
}
return 0;
}
if ( notifyCode == CBN_SELCHANGE )
{
// selection changed in combo box
}
DialogBoxParam. The DialogBoxParam function creates a modal dialog box from a dialog
box template resource. Before displaying the dialog box, the function passes an
application-defined value to the dialog box procedure as the lParam parameter of the
WM_INITDIALOG message. An application can use this value to initialize dialog box
controls.
DialogBoxIndirect. The DialogBoxIndirect function creates a modal dialog box from a dialog
box template in memory. The DialogBoxIndirect function does not return control until the
specified callback function terminates the modal dialog box by calling the EndDialog
function.
an application-defined value to the dialog box procedure as the lParam parameter of the
WM_INITDIALOG message. An application can use this value to initialize dialog box
controls.
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
Page 117
CreateDialog. The CreateDialog function creates a modeless dialog box from a dialog box template
resource.
CreateDialogParam. The CreateDialogParam function creates a modeless dialog box from a dialog
box template resource. Before displaying the dialog box, the function passes an application-defined
value to the dialog box procedure as the lParam parameter of the WM_INITDIALOG message. An
application can use this value to initialize dialog box controls.
Even if an application has no other user input, it usually has one specific dialog box. The "About" dialog
box is a dialog box displayed by an About menu option. This dialog box displays the name of the
application, its copyright notice, and version information, along with any other descriptive or useful
information. Some applications even have hidden "Easter egg" screens accessed through the About box.
The first step in adding a dialog box to an application is to create the dialog box template. The dialog box
template is a textual specification for the dialog box. It is possible to create the dialog template manually
in a text editor; however, tools such as the Visual C++ Developer Studio enable dialog boxes to be created
graphically. The dialog box template for the About box in the TravelManager application appears as the
following code:
ABOUTBOX DIALOG DISCARDABLE 60, 30, 150, 74
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION |
WS_SYSMENU
CAPTION "About TravelManager"
FONT 8, "MS Shell Dlg"
Page 118
BEGIN
PUSHBUTTON
LTEXT
ICON
END
"OK",IDOK,66,55,40,14
"TravelManager",-1,42,14,108,28
IDI_APPICON,-1,11,10,18,20
The format of the DIALOG resource is the same under Windows CE as under Win32. The template
specifies attributes about the dialog box and the controls that will be displayed on the dialog box. Our
ABOUTBOX dialog box has an icon, static text, and an OK button. (More about controls will be explored
further in Chapter 7, "Controls.") The dialog box template also specifies the specific style of a dialog box.
Warning
Under Windows CE, there are restrictions on the styles that can be specified after the
STYLE keyword.
The following includes a list of restricted styles or styles that aren't supported in Windows CE:
DS_SETFONT. You cannot set the font inside dialog boxes.
DS_RECURSE. Not required. Any child dialog box is automatically considered to be a recursive
dialog box.
Page 119
DS_NOIDLEMSG. Not currently supported.
After the dialog template is defined, displaying a modal dialog box is done with the DialogBoxParam
function:
DialogBoxParam(m_pApp->m_hInst, TEXT("AboutBox"), hWnd,
(DLGPROC)DlgProc, NULL);
The parameters of the DialogBoxParam function in Windows CE are the same as under Win32. The
parameters to DialogBoxParam specify the application instance, the dialog box identifier, the parent
window, the dialog procedure, and a user-defined data value.
=
=
=
=
=
=
=
=
=
=
0 ;
(WNDPROC) WndProc;
0;
4;
// *** Extra space for C++ ptr ***
m_hInst;
NULL;
NULL;
(HBRUSH) GetStockObject(WHITE_BRUSH);
NULL;
szClassName;
if ( !RegisterClass(&wc) )
{
return FALSE;
}
...
Step 2: Pass the pointer to the C++ class in the CreateWindow function.
The last parameter of the CreateWindow function is any user data that will be sent with the
WM_CREATE message.
BOOL MainWindow::Create()
{
HWND hWnd = CreateWindow(szClassName,
szTitle,
WS_VISIBLE,
0,
Page 121
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
m_pApp->m_hInst,
this);
// *** ptr to `this' class ***
...
Step 3: Set the C++ pointer when processing the WM_CREATE message.
The user data value that was passed in the CreateWindow function is received in the WndProc function in
the WM_CREATE message. The lParam value specifies a pointer to a CREATESTRUCT structure, and
the lpCreateParams member holds the user data value.
The SetWindowLong function is used to set the user data value in the extra space allocated for the
window class. The SetWindowLong function takes a window handle, some user data value, and an offset
into the extra window space. Because the TravelManager application uses only one "slot" of extra space,
zero is specified as the offset.
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam )
{
if (msg == WM_CREATE)
{
LPCREATESTRUCT lpStruct = (LPCREATESTRUCT) lParam;
Window * pWindow = (Window *) lpStruct->lpCreateParams;
SetWindowLong(hWnd, 0, (LONG)pWindow);
pWindow->WMCreate(hWnd);
return 0;
}
...
Step 4: Retrieve the C++ pointer when processing other messages.
Using the GetWindowLong function, the user data value is retrieved from the window.
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
By using C++ inheritance, the need to know exactly which class type can be effectively eliminated. If ItineraryView and
ExpensesView inherit from the same base class, that class type can be used for the pointer. The TravelManager application
uses a base class named Window and derives those view classes from this base class. The following source code
demonstrates this:
class Window
{
public:
Window() {}
~Window() {}
virtual BOOL Create() {return FALSE;}
virtual void WMCreate(HWND) {}
virtual void WMPaint() {}
virtual LRESULT WMCommand(HWND, UINT, WPARAM, LPARAM) { return 0; }
virtual LRESULT WMNotify(HWND, UINT, WPARAM, LPARAM) { return 0; }
HWND m_hWnd;
};
Page 124
BOOL Create();
LRESULT WMCommand( HWND, UINT, WPARAM, LPARAM ) {return 0;}
...
};
class ExpensesView : public Window
{
public:
ExpensesView(MainWindow *);
~ExpensesView();
BOOL Create();
LRESULT WMCommand( HWND, UINT, WPARAM, LPARAM ) { return 0;}
...
};
By using a base class when the C++ pointer is returned with the GetWindowLong function, it is of type Window. Given an
object of type Window, the proper method can then be called (for instance, the WMCommand method when a
WM_COMMAND message is received). Because the WMCommand is virtual, the WMCommand method that actually gets
executed will depend on which type the object really is (for instance, the WMCommand in the ExpensesView if the C++
pointer points to an ExpensesView object). If these concepts are unfamiliar, there are many excellent C++ books that can
provide much greater detail on inheritance and virtual functions.
The procedure for linking the dialog box procedure (DlgProc) with the corresponding C++ class for the dialog box is nearly
identical to the steps covering on the WndProc earlier. The only difference is that Windows CE supports the DWL_USER
offset, so it is not necessary to create a new window class with extra space for the dialog boxes. The DWL_USER offset can
be used with SetWindowLong and GetWindowLong for storing and retrieving the C++ object pointer.
TravelManager Application
The source code for the TravelManager application started in this chapter can be found on the accompanying CD-ROM.
Refer to Appendix
Page 125
A, "Getting Started with the CD-ROM," for information on accessing the source code on the CD-ROM.
Because this chapter lays the foundation for an application that will be extended in additional chapters, the source code for
the initial TravelManager application is also listed at the end of this chapter.
This initial version of the application has many important components and classes. The main classes and components of the
application include the following:
TravelManagerApp. The application class has a Create method for creating the main window and a Run method for
holding the message loop.
Window. The base class from which all subsequent window classes will be derived.
MainWindow. The class for the main window, which has methods for creating the main window, creating the
command bar, and processing certain messages.
DlgProc. The dialog box procedure dispatches messages to the correct object.
WndProc. The window procedure, which dispatches messages to the correct object.
WinMain. The entry point into the application, which creates the application class and waits for it to exit.
#include <windows.h>
#include "resource.h"
#include "commctrl.h"
// Class name and window title
WCHAR szClassName[] = TEXT("TRVLMGR");
WCHAR szTitle[] = TEXT("TravelManager");
// The application class
class TravelManagerApp
{
Page 126
public:
TravelManagerApp();
~TravelManagerApp(){}
BOOL Create(HINSTANCE);
int Run();
HINSTANCE m_hInst;
};
class Window
{
public:
Window() {}
~Window() {}
virtual BOOL Create() {return FALSE;}
virtual void WMCreate(HWND) {}
virtual void WMPaint() {}
virtual LRESULT WMCommand(HWND, UINT, WPARAM, LPARAM) { return 0; }
HWND m_hWnd;
};
// The main window class
class MainWindow : public Window
{
public:
MainWindow(TravelManagerApp *);
~MainWindow() {}
BOOL Create();
void CreateCommandBar();
void WMCreate(HWND);
LRESULT WMCommand( HWND, UINT, WPARAM, LPARAM );
TravelManagerApp * m_pApp;
HWND m_hwndCB;
HWND m_hwndCombo;
};
Page 127
// forward declaration
BOOL APIENTRY DlgProc( HWND, UINT, WPARAM, LPARAM);
// Implementation of MainWindow methods
MainWindow::MainWindow(TravelManagerApp * pApp)
{
m_pApp = pApp;
}
void MainWindow::WMCreate(HWND hWnd)
{
m_hWnd = hWnd;
LONG lStyle = GetWindowLong(hWnd, GWL_STYLE);
lStyle & ~WS_CAPTION;
SetWindowLong(hWnd, GWL_STYLE, lStyle);
CreateCommandBar();
}
void MainWindow::CreateCommandBar()
{
static TBBUTTON tbButton[] = {
{0,
0,
TBSTATE_ENABLED, TBSTYLE_SEP,
0, 0, 0,
_1},
{0,
0,
TBSTATE_ENABLED, TBSTYLE_SEP,
0, 0, 0,
_1},
{STD_CUT,
ID_EDIT_CUT,
TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0,
0},
{STD_COPY,
ID_EDIT_COPY,
TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0,
_1},
{STD_PASTE,
ID_EDIT_PASTE,
TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0,
_1},
{0,
0,
TBSTATE_ENABLED, TBSTYLE_SEP,
0, 0, 0,
0},
{15,
ID_VIEW_ITINERARY,
TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0,
_1},
{16,
ID_VIEW_EXPENSES,
{17,
{0,
ID_VIEW_NOTES,
0,
TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0,
_1},
TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0, _1},
TBSTATE_ENABLED, TBSTYLE_SEP,
0, 0, 0,
0},
};
Keyword
Brief
Full
Advanced
Search
Search Tips
Page 129
if (m_hwndCombo)
{
SendMessage(m_hwndCombo,
SendMessage(m_hwndCombo,
SendMessage(m_hwndCombo,
SendMessage(m_hwndCombo,
SendMessage(m_hwndCombo,
CB_ADDSTRING,
CB_ADDSTRING,
CB_ADDSTRING,
CB_ADDSTRING,
CB_ADDSTRING,
0,
0,
0,
0,
0,
(LPARAM)L"Airline");
(LPARAM)L"Car Rental");
(LPARAM)L"Hotel");
(LPARAM)L"Expenses");
(LPARAM)L"Notes");
if ( notifyCode == 0)
{
switch (LOWORD(wParam))
{
case ID_HELP_ABOUT:
DialogBoxParam(m_pApp->m_hInst, TEXT("AboutBox"), hWnd,
(DLGPROC)DlgProc, NULL);
break;
case ID_VIEW_ITINERARY:
case ID_VIEW_EXPENSES:
case ID_VIEW_NOTES:
// Check the appropriate menu item
HMENU hMenu = CommandBar_GetMenu(m_hwndCB,0);
CheckMenuItem(hMenu, ID_VIEW_ITINERARY, MF_UNCHECKED);
CheckMenuItem(hMenu, ID_VIEW_EXPENSES, MF_UNCHECKED);
CheckMenuItem(hMenu, ID_VIEW_NOTES, MF_UNCHECKED);
CheckMenuItem(hMenu, LOWORD(wParam), MF_CHECKED);
// Toggle the appropriate command bar button
SendMessage(m_hwndCB, TB_SETSTATE,
Page 130
(WPARAM)ID_VIEW_ITINERARY, MAKELONG(TBSTATE_ENABLED,0));
SendMessage(m_hwndCB, TB_SETSTATE, (WPARAM)ID_VIEW_EXPENSES,
MAKELONG(TBSTATE_ENABLED,0));
SendMessage(m_hwndCB, TB_SETSTATE, (WPARAM)ID_VIEW_NOTES,
MAKELONG(TBSTATE_ENABLED,0));
SendMessage(m_hwndCB, TB_SETSTATE, (WPARAM)LOWORD(wParam),
MAKELONG(TBSTATE_ENABLED|TBSTATE_CHECKED,0));
// Select something in theh combo box
if (LOWORD(wParam) == ID_VIEW_ITINERARY)
{
SendMessage(m_hwndCombo, CB_SETCURSEL, 0, 0);
}
if (LOWORD(wParam) == ID_VIEW_EXPENSES)
{
SendMessage(m_hwndCombo, CB_SETCURSEL, 3, 0);
}
if (LOWORD(wParam) == ID_VIEW_NOTES)
{
SendMessage(m_hwndCombo, CB_SETCURSEL, 4, 0);
}
break;
}
return 0;
}
if ( notifyCode == CBN_SELCHANGE )
{
// Clear view buttons and menu items
SendMessage(m_hwndCB, TB_SETSTATE, (WPARAM)ID_VIEW_ITINERARY,
MAKELONG(TBSTATE_ENABLED,0));
SendMessage(m_hwndCB, TB_SETSTATE, (WPARAM)ID_VIEW_EXPENSES,
MAKELONG(TBSTATE_ENABLED,0));
SendMessage(m_hwndCB, TB_SETSTATE, (WPARAM)ID_VIEW_NOTES,
MAKELONG(TBSTATE_ENABLED,0));
HMENU hMenu = CommandBar_GetMenu(m_hwndCB,0);
CheckMenuItem(hMenu, ID_VIEW_ITINERARY, MF_UNCHECKED);
CheckMenuItem(hMenu, ID_VIEW_EXPENSES, MF_UNCHECKED);
Page 131
BOOL MainWindow::Create()
{
HWND hWnd = CreateWindow(szClassName,
szTitle,
WS_VISIBLE,
0,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
m_pApp->m_hInst,
//
//
//
//
//
//
//
//
//
//
class name
window title
styles
x position
y position
width
height
parent
menu
instance handle
this);
// user data
Page 132
Page 133
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
if (msg == WM_CREATE)
{
LPCREATESTRUCT lpStruct = (LPCREATESTRUCT) lParam;
Window * pWindow = (Window *) lpStruct->lpCreateParams;
SetWindowLong(hWnd, 0, (LONG)pWindow);
pWindow->WMCreate(hWnd);
return 0;
}
Page 134
m_hInst = hInstance;
wc.style
wc.lpfnWndProc
wc.cbClsExtra
wc.cbWndExtra
wc.hInstance
wc.hIcon
wc.hCursor
wc.hbrBackground
wc.lpszMenuName
wc.lpszClassName
=
=
=
=
=
=
=
=
=
=
0 ;
(WNDPROC) WndProc;
0;
4;
m_hInst;
NULL;
NULL;
(HBRUSH) GetStockObject(WHITE_BRUSH);
NULL;
szClassName;
if ( !RegisterClass(&wc) )
{
return FALSE;
}
// RegisterClass worked, so create the window
MainWindow * pMainWindow = new MainWindow(this);
if ( !pMainWindow )
{
return FALSE;
}
if ( !pMainWindow->Create() )
{
return FALSE;
}
return TRUE;
}
int TravelManagerApp::Run()
{
MSG msg;
// Main window was created, start the message loop
while ( GetMessage(&msg, NULL, 0, 0) != FALSE )
{
TranslateMessage (&msg) ;
DispatchMessage(&msg);
}
Page 135
return(msg.wParam);
}
int WINAPI WinMain ( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nCmdShow )
{
// Is there another instance already running
if ( hPrevInstance != 0 )
{
return _1;
}
TravelManagerApp * pApp = new TravelManagerApp();
if ( !pApp )
{
return _1;
}
if ( pApp->Create(hInstance) == FALSE )
{
return _1;
}
BOOL exitVal = pApp->Run();
delete pApp;
return exitVal;
}
Page 136
Previous | Table of Contents | Next
CHAPTER 7
Controls
In the last chapter, a command bar was created that was comprised of a menu
with button and combo box controls. You also created a dialog box that
contained icon, text, and button controls. These controls are preconstructed
elements in Windows CE that enable different Windows CE applications to
look and act alike.
Controls have been part of the operating system since the earliest days of
Windows. Windows CE carries on the tradition of controls by supporting
nearly all the controls that are part of Windows 95. Support
for Windows 95 controls enables a Windows CE application to have the same
look and feel as a Windows 95 application. Table 7.1 summarizes the controls
from Windows 95 and their support under Windows CE.
Page 138
Table 7.1
Windows 95 Controls Supported Under Windows CE
Control
Check boxes
Column headings
Command bars
Command buttons
Supported Comments
Yes
Yes
The command bar only
supports drop-down
Yes
menus, drop-down combo
boxes, and toolbar
buttons.
Yes
Yes
No
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Toolbars
No
Tooltips
Yes
Up-down buttons
Yes
Page 139
Control Basics
Controls are created either as part of a dialog box template structure or through
the CreateWindow function because controls themselves are windows. The
type of control is specified by the class name, such as button, edit, or
SysListView32. Other attributes that must be specified when creating a control
window include a child window identifier, size, position information, and the
control's parent window. Style information is also used when creating the
control; these styles specify the look and functionality of the control. Styles for
each control will be defined in the following sections.
A program interacts with a control by sending messages to the control. These
messages enable the application to set and query information about the control.
In addition, the control notifies the application of various events by sending
the control's parent window a message. This interaction with controls follows
the same mechanisms as it would under Win32. The messages allowed for
each control will be defined throughout this chapter.
Common Styles
In addition to control-specific styles, there are a number of window styles that
can also be used when creating controls. The WS_BORDER style specifies
that the control has a thin border. The WS_VISIBLE style creates a window
that is initially visible. The WS_GROUP and WS_TABSTOP are used to set
which controls can be tabbed. The WS_CHILD style creates a child window.
The WS_DISABLED style creates a window that is initially disabled. The
WS_HSCROLL and WS_VSCROLL add horizontal or vertical scroll bars to
the window.
Note
Windows CE does not support the following window styles:
WS_CHILDWINDOW, WS_ICONIC, WS_MAXIMIZE,
WS_MAXIMIZEBOX, WS_MINIMIZE, WS_MINIMIZEBOX,
WS_OVERLAPPED, WS_OVERLAPPEDWINDOW,
WS_POPUPWINDOW, WS_SIZEBOX, WS_THICKFRAME,
WS_TILED, and WS_TILEDWINDOW.
Page 140
Common Messages and Functions
There are a few messages that can be used with multiple controls. These
messages include WM_CUT, WM_COPY, WM_PASTE, and WM_CLEAR
for dealing with the clipboard; the WM_SETFONT and WM_GETFONT for
setting and retrieving the font used in the control; and the WM_SETTEXT and
WM_GETTEXT for setting and getting the window's text (or the
SetWindowText and GetWindowText functions). Another variation of the
WM_SETTEXT and WM_GETTEXT messages are the functions
GetDlgItemText and SetDlgItemText, which enable manipulation of a control
in a dialog box by specifying the control ID.
Button Control
One of the most versatile predefined controls is the button control. This control
is used to display push buttons, check boxes, radio buttons, and even group
boxes. Essentially, a button control defines a small rectangular region that
usually changes state when clicked.
Button Styles
The appearance of the button's control is specified through style flags. The
style flags available in Windows CE are listed in Table 7.2.
Table 7.2
Button Styles in Windows CE
Style
BS_3STATE
Description
Creates a button that is the same as a
check box, except that the box can be
grayed as well as checked or unchecked.
Use the grayed state to show that the state
of the check box is not determined.
Description
Creates a button that is the same
as a check box, except that the
check state automatically toggles
BS_AUTOCHECKBOX
between checked and unchecked
each time the user selects the
check box.
Creates a button that is the same
as a radio button, except that
when the user selects it,
Windows automatically sets the
BS_AUTORADIOBUTTON
button's check state to checked
and automatically sets the check
state for all other buttons in the
same group to unchecked.
Specifies that the button displays
BS_BITMAP
a bitmap.
Places text at the bottom of the
BS_BOTTOM
button rectangle.
Centers text horizontally in the
BS_CENTER
button rectangle.
Creates a small, empty check box
with text. By default, the text is
displayed to the right of the
BS_CHECKBOX
check box. To display the text to
the left of the check box,
combine this flag with the
BS_RIGHTBUTTON style.
Creates a push button that
behaves like a
BS_PUSHBUTTON-style
button, but also has a heavy
black border. If the button is in a
dialog box, the user can select
BS_DEFPUSHBUTTON
the button by pressing the Enter
key, even when the button does
not have the input focus. This
style is useful for enabling the
user to quickly select the most
likely (default) option.
BS_GROUPBOX
Keyword
Brief
Full
Advanced
Search
Search Tips
Table 7.2
Button Styles in Windows CE, continued
Style
BS_ICON
Description
Specifies that the button displays an icon.
Left-aligns the text in the button
rectangle. However, if the button is a
check box or radio button that does not
BS_LEFT
have the BS_RIGHTBUTTON style, the
text is left-aligned on the right side of the
check box or radio button.
Enables a button to send BN_DBLCLK,
BN_KILLFOCUS, and BN_SETFOCUS
notification messages to its parent
BS_NOTIFY
window. Note that buttons send the
BN_CLICKED notification message
regardless of whether it has this style.
Creates an owner-drawn button. The
owner window receives a
WM_MEASUREITEM message when
the button is created and a
BS_OWNERDRAW
WM_DRAWITEM message when a
visual aspect of the button has changed.
Do not combine the BS_OWNERDRAW
style with any other button styles.
Creates a push button that posts a
BS_PUSHBUTTON WM_COMMAND message to the owner
window when the user selects the button.
Makes a button (such as a check box,
three-state check box, or radio button)
look and act like a push button. The
BS_PUSHLIKE
button looks raised when it isn't pushed
or checked, and sunken when it is pushed
or checked.
Page 143
Style
Description
Description
Used to retrieve the state of a radio button
BM_GETCHECK or check box. The return value indicates the
state.
Value
0
1
Meaning
unchecked
checked
indeterminate (applies only to
2
BS_(AUTO)3STATE styles.)
Used to set the check state of a radio button
BM_SETCHECK
or check box.
BM_GETSTATE Used to determine the state of the button.
Used to set the state of the button. A
BM_SETSTATE WPARAM of TRUE highlights the button;
FALSE removes any highlighting.
BM_SETSTYLE Used to change the style of the button.
Simulates the user clicking a button. This
message causes the button to receive a
WM_LBUTTONDOWN and a
BM_CLICK
WM_LBUTTONUP message, and the
button's parent window receives a
BN_CLICKED notification message.
Button Notifications
Despite the wide range of appearances that the button control can take, it provides one main notification message,
BN_CLICKED. This notification is sent by Windows CE when the user taps the button with the
Page 145
stylus or selects the highlighted button by pressing the Enter key. The parent window of the button control receives
the BN_CLICKED notification in the form of a WM_COMMAND message.
The TravelManager application handles the BN_CLICKED notification when it processes the WM_COMMAND
message for the ItineraryView window. That process appears as the following code:
ItineraryView::WMCommand( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
WORD notifyCode = HIWORD(wParam);
WORD id = LOWORD(wParam);
if (notifyCode == BN_CLICKED && id == IDC_BUTTON1)
{
FlightInfoDlg * pDlg = new FlightInfoDlg(m_pMainWindow);
pDlg->Create();
return 1;
}
return 0;
}
Static Controls
Static controls define a simple text field, box, or rectangle used to label, box, or separate other controls. Static
controls take no input and provide no output.
Static Styles
The styles valid when creating a static control are listed in Table 7.4.
Page 146
Table 7.4
Static Control Styles
Style
SS_BITMAP
SS_CENTER
Description
Specifies that a bitmap is to be displayed
in the static control. The error code text
is the name of a bitmapnot a file
name defined elsewhere in the
resource file. The style ignores the
nWidth and nHeight parameters, and the
control automatically sizes itself to
accommodate the bitmap.
Specifies a simple rectangle and centers
the error code text in the rectangle. The
text is formatted before it is displayed,
and words that extend past the end of a
line are automatically wrapped to the
beginning of the next centered line.
Description
Specifies a simple rectangle and
left-aligns the given text in the
rectangle. The text is formatted
before it is displayed, and words
SS_LEFT
that extend past the end of a line
are automatically wrapped to the
beginning of the next left-aligned
line.
Specifies a simple rectangle and
left-aligns the given text in the
rectangle. Tabs are expanded but
SS_LEFTNOWORDWRAP
words are not wrapped, and text
that extends past the end of a line
is clipped.
Prevents interpretation of any
ampersand (&) characters in the
control's text as accelerator prefix
characters. These are displayed
with the ampersand removed and
the next character in the string
underlined. This static control
style may be included with any of
SS_NOPREFIX
the defined static controls. An
application can combine
SS_NOPREFIX with other styles
by using the bitwise or (|)
operator. This can be useful when
file names or other strings that
may contain an ampersand (&)
must be displayed as a static
control in a dialog box.
Sends the parent window
STN_CLICKED and
SS_NOTIFY
STN_DBLCLK notification
messages when the user clicks or
double-clicks the control.
SS_RIGHT
Note
Windows CE does not support the SS_BLACKFRAME,
SS_BLACKRECT, SS_GRAYFRAME, SS_GRAYRECT,
SS_METARECT, SS_RIGHTIMAGE, SS_SIMPLE,
SS_WHITEFRAME, or SS_WHITERECT styles.
Static Control Messages
Due to the fact that static controls provide little functionality, no messages or
functions are specific to static controls. It is common, however, to use the general
WM_SETTEXT message (or corresponding
SetWindowText function) with static controls. For dialog boxes, the SetDlgItemText
function makes it convenient to change the text of the control. The TravelManager
application uses SetDlgItemText to change the text of static controls in response to
the user selecting entries out of the tree control in the Alternate Flight Lookup dialog
box.
SetDlgItemText(hWnd, IDC_FROM, L"Seattle");
SetDlgItemText(hWnd, IDC_TO, L"Indianapolis");
SetDlgItemText(hWnd, IDC_DEPARTS, L"8:20 am");
SetDlgItemText(hWnd, IDC_ARRIVES, L"4:45 pm");
SetDlgItemText(hWnd, IDC_AIRLINE, L"Delta");
SetDlgItemText(hWnd, IDC_CONNECTION, L"Atlanta");
SetDlgItemText(hWnd, IDC_LAYOVER, L"1:10");
At this stage in the development of the TravelManager application, the data
displayed in the static controls is hard-coded. The text to display would eventually
come out of a database or other mechanism and be selectively displayed based on the
node selected in the tree control.
Static Notifications
As noted previously, static controls with the SS_NOTIFY style enable the parent to
receive STN_CLICKED and STD_DBLCLK notification messages when the user
clicks or double-clicks the control.
Page 149
Description
Designates a horizontal scroll bar. If the
SBS_TOPALIGN style is not specified,
SBS_HORZ
the scroll bar has the height, width, and
position specified by the parameters of
CreateWindow.
Aligns the left edge of the scroll bar with
the left edge of the rectangle defined by the
parameters of CreateWindow. The scroll
SBS_LEFTALIGN
bar has the default width for system scroll
bars. Use this style with the SBS_VERT
style.
Designates a size box with the height,
SBS_SIZEBOX width, and position specified by the
parameters of CreateWindow.
Aligns the top edge of the scroll bar with
the top edge of the rectangle defined by the
parameters of CreateWindow. The scroll
SBS_TOPALIGN
bar has the default height for system scroll
bars. Use this style with the SBS_HORZ
style.
Page 150
Table 7.5
Scroll Bar Control Styles, continued
Style
Description
Function
Description
Retrieves the
parameters of a scroll
bar including the
minimum and
SBM_GETSCROLLINFO GetScrollInfo maximum scrolling
positions, the page
size, and the position
of the scroll box
(thumb).
Page 151
Message
Function
Description
Sets the parameters of
a scroll bar, including
the minimum and
maximum scrolling
SBM_SETSCROLLINFO SetScrollInfo
positions, the page
size, and the position
of the scroll box
(thumb).
Scroll Bar Control Notifications
An application is notified of scroll events through the WM_HSCROLL and
WM_VSCROLL messages. These events are received in the form of a
WM_COMMAND message and are shown in Table 7.7.
Table 7.7
Scroll Bar Control Notifications
Notification
Description
Indicates that a scroll event has occurred with
WM_HSCROLL
a horizontal scroll bar.
Indicates that a scroll event has occurred with
WM_VSCROLL
a vertical scroll bar.
Edit Control
Edit controls are rectangular child windows into which the user can type text from
the keyboard. Edit controls are simple mechanisms for enabling data entry. The
TravelManager application uses edit controls in the Add/Edit Expense dialog box
shown in Figure 7.1.
Edit Control Styles
The styles shown in Table 7.8 are valid when creating an edit control.
Page 152
Figure 7.1
The Add/Edit Expense dialog box.
Table 7.8
Edit Control Styles
Style
Description
Automatically scrolls text to the right
by 10 characters when the user types a
character at the end of the line. When
ES_AUTOHSCROLL
the user presses the Enter key, the
control scrolls all text back to position
zero.
Automatically scrolls text up one page
ES_AUTOVSCROLL when the user presses the Enter key on
the last line.
ES_CENTER
Centers text in a multiline edit control.
Indicates that the edit control is part of a
ES_COMBOBOX
combo box.
ES_LEFT
Left-aligns text.
Converts all characters to lowercase as
ES_LOWERCASE
they are typed into the edit control.
ES_MULTILINE
Designates a multiline edit control.
Page 153
Style
Description
Table 7.9
Edit Control Messages
Message
Description
Determines whether an
edit-control operation can be
EM_CANUNDO
undone; that is, whether the
control can respond to the
EM_UNDO message.
Retrieves the zero-based
character index and zero-based
EM_CHARFROMPOS
line index of the character
nearest the specified point in
an edit control.
Resets the undo flag of an edit
control. The undo flag is set
EM_EMPTYUNDOBUFFER
whenever an operation within
the edit control can be undone.
Finds the next word break
before or after the specified
EM_FINDWORDBREAK
character position, or retrieves
information about the
character at that position.
EM_GETMODIFY
EM_GETPASSWORDCHAR
EM_GETRECT
EM_GETSEL
Description
Retrieves the widths of the
left and right margins for an
edit control.
Determines whether the
content of an edit control has
been modified.
Retrieves the password
character displayed in an edit
control when the user enters
text.
Retrieves the formatting
rectangle of an edit control.
The formatting rectangle is
the limiting rectangle of the
text. The limiting rectangle is
independent of the size of the
edit-control window.
Retrieves the starting and
ending character positions of
the current selection in an edit
control.
EM_REPLACESEL
EM_SCROLL
EM_SCROLLCARET
Description
Retrieves the coordinates of the
specified character in an edit
control.
Replaces the current selection in
an edit control with the specified
text.
Scrolls the text vertically in a
multiline edit control. This
message is equivalent to sending
a WM_VSCROLL message to
the edit control.
Scrolls the caret into view in an
edit control.
EM_SETRECT
Description
Sets the formatting rectangle
of a multiline edit control. The
formatting rectangle is the
limiting rectangle of the text.
The limiting rectangle is
independent of the size of the
edit control window. When
the edit control is first created,
the formatting rectangle is the
same as the client area of the
edit control window. By using
the EM_SETRECT message,
an application can make the
formatting rectangle larger or
smaller than the edit control
window.
Description
Indicates the user has modified text in an
EN_CHANGE
edit control.
Indicates the edit control cannot allocate
EN_ERRSPACE
enough memory to meet a specific request.
Indicates the user has clicked the edit
EN_HSCROLL
control's horizontal scroll bar.
Indicates the user has selected another
EN_KILLFOCUS
control.
Table 7.11
List Box Control Styles
Style
Description
Shows a disabled vertical scroll
bar for the list box when the
box does not contain enough
LBS_DISABLENOSCROLL items to scroll. If you do not
specify this style, the scroll bar
is hidden when the list box
does not contain enough items.
Permits multiple items to be
selected by using the Shift key
LBS_EXTENDEDSEL
and the mouse or a special key
combination.
Specifies that a list box
contains items consisting of
strings. The list box maintains
the memory and addresses for
the strings so the application
can use the LB_GETTEXT
LBS_HASSTRINGS
message to retrieve the text for
a particular item. By default,
all list boxes except
owner-drawn list boxes have
this style. You can create an
owner-drawn list box with or
without this style.
Specifies a multicolumn list
box that is scrolled
horizontally. The
LBS_MULTICOLUMN
LB_SETCOLUMNWIDTH
message sets the width of the
columns.
Turns string selection on or off
each time the user clicks or
LBS_MULTIPLESEL
double-clicks a string in the list
box. The user can select any
number of strings.
Description
Specifies that the list box's
appear-ance is not updated
when changes are made.
LBS_NOREDRAW
You can change this style at
any time by sending a
WM_SETREDRAW
message.
Specifies that the list box
LBS_NOSEL
contains items that can be
viewed but not selected.
Notifies the parent window
with an input message
LBS_NOTIFY
whenever the user clicks or
double-clicks a string in the
list box.
Sorts strings in the list box
LBS_SORT
alpha-betically.
Enables a list box to
recognize and expand tab
characters when drawing its
strings. The default tab
positions are 32 dialog box
units. A dialog box unit is a
horizontal or vertical
LBS_USETABSTOPS
distance. One horizontal
dialog box unit is equal to
one-fourth of the current
dialog box base-width unit.
Windows calculates these
units based on the height
and width of the current
system font.
Specifies that the owner of
the list box receives
WM_VKEYTOITEM
messages whenever the user
presses
LBS_WANTKEYBOARDINPUT
a key and the list box has
the input focus. This
enables an application to
perform special processing
on the keyboard input.
Page 161
Note
Windows CE does not support the LBS_NODATA, LBS_OWNERDRAWFIXED,
LBS_OWNERDRAWVARIABLE, or LBS_STANDARD styles.
List Box Control Messages and Functions
List box controls support a number of messages used to control the functionality of the control. These
messages are described in Table 7.12.
Table 7.12
List Box Control Messages
Message
Description
Adds the specified file name to a
LB_ADDFILE
list box that contains a directory
listing.
Adds a string to a list box. If the
list box does not have the
LBS_SORT style, the string is
LB_ADDSTRING
added to the end of the list.
Otherwise, the string is inserted
into the list and the list is sorted.
LB_DELETESTRING
Deletes a string in a list box.
Adds a list of file names to a list
LB_DIR
box.
Finds the first string in a list box
LB_FINDSTRING
that contains the specified prefix.
Finds the first list box string that
LB_FINDSTRINGEXACT matches the string specified in the
lpszFind parameter.
Retrieves the index of the anchor
item, which is the item from which
a multiple selection starts. A
LB_GETANCHORINDEX
multiple selection spans all items
from the anchor item to the caret
item.
continues
Page 162
Table 7.12
List Box Control Messages, continued
Message
LB_GETCARETINDEX
LB_GETCOUNT
LB_GETCURSEL
Description
Determines the index of the
item that has the focus
rectangle in a
multiple-selection list box.
The item may or may not
be selected.
Retrieves the number of
items in a list box.
Retrieves the index of the
currently selected item, if
any, in a single- selection
list box.
LB_GETTOPINDEX
LB_INITSTORAGE
Description
Fills a buffer with an array of
integers that specify the item
numbers of selected items in a
multiple-selection list box.
Retrieves a string from a list box.
Retrieves the length of a string in a
list box.
Retrieves the index of the first
visible item in a list box. Initially,
the item with index 0 is at the top
of the list box, but if the list box
contents have been scrolled,
another item may be at the top.
Allocates memory for storing list
box items. An application sends
this message before adding a large
number of items to a list box.
Table 7.12
List Box Control Messages, continued
Message
LB_SETANCHORINDEX
LB_SETCARETINDEX
LB_SETCOLUMNWIDTH
LB_SETCOUNT
LB_SETCURSEL
Description
Sets the anchor item, which
is the item from which a
multiple selection starts. A
multiple selection spans all
items from the anchor item
to the caret item.
Sets the focus rectangle to
the item at the specified
index in a
multiple-selection list box.
If the item is not visible, it
is scrolled into view.
Sets the width, in pixels, of
all columns in the list box.
Sets the count of items in a
list box created with the
LBS_NODATA style and
not created with the
LBS_HASSTRINGS style.
Selects a string and scrolls
it into view, if necessary.
When a new string is
selected, the list box
removes the highlight from
the previously selected
string.
Description
Sets the height, in pixels, of items in a
list box. If the list box has the
LBS_OWNERDRAWVARIABLE
style, this message sets the height of
LB_SETITEMHEIGHT
the item specified by the index
parameter. Otherwise, this message
sets the height of all items in the list
box.
Sets the current locale of the list box.
You can use the locale to determine
the correct sorting order of displayed
LB_SETLOCALE
text (for list boxes with the
LBS_SORT style) and of text added
by the LB_ADDSTRING message.
Selects a string in a multiple-selection
LB_SETSEL
list box.
Sets the tab-stop positions in a list
LB_SETTABSTOPS
box.
Ensures that a particular item in a list
LB_SETTOPINDEX
box is visible.
Description
Indicates a string has been double-clicked.
Indicates the list box cannot allocate
LBN_ERRSPACE
enough memory to meet a specific request.
continues
Page 166
Table 7.13
Description
Indicates the list box has lost key- board
LBN_KILLFOCUS
focus.
Indicates the user has canceled the
LBN_SELCANCEL
selection in the list box.
Indicates the selection in the list box is
LBN_SELCHANGE
about to change.
Indicates the list box has received
LBN_SETFOCUS
keyboard focus.
Description
Automatically scrolls the text in an
edit control to the right when the user
types a character at the end of the line.
CBS_AUTOHSCROLL
If this style is not set, only text that
fits within the rectangular boundary is
permitted.
Page 167
Style
Description
Shows a disabled vertical
scroll bar in the list box when
the box does not contain
CBS_DISABLENOSCROLL enough items to scroll. Without
this style, the scroll bar is
hidden when the list box does
not contain enough items.
Displays a combo box where
the list box is not displayed
CBS_DROPDOWN
unless the user selects an icon
next to the edit control.
Similar to CBS_DROPDOWN,
except that the edit control is
CBS_DROPDOWNLIST
replaced by a static text item
that displays the current
selection in the list box.
CB_ADDSTRING
Description
Adds a string to the list box of a
combo box. If the combo box does
not have the CBS_SORT style, the
string is added to the end of the
list. Otherwise, the string is
inserted into the list, and the list is
sorted.
Keyword
Brief
Full
Advanced
Search
Search Tips
Message
Description
Retrieves the screen
coordinates of the
CB_GETDROPPEDCONTROLRECT
drop-down list box of a
combo box.
Determines whether the
CB_GETDROPPEDSTATE
list box of a combo box
is dropped down.
Retrieves the minimum
acceptable width, in
pixels, of the list box of a
CB_GETDROPPEDWIDTH
combo box with the
CBS_DROPDOWN or
CBS_DROPDOWNLIST
style.
Retrieves the starting and
ending character
CB_GETEDITSEL
positions of the current
selection in the edit
control of a combo box.
CB_GETEXTENDEDUI
CB_GETHORIZONTALEXTENT
CB_GETITEMDATA
CB_GETITEMHEIGHT
CB_GETLBTEXT
CB_GETLBTEXTLEN
Determines whether a
combo box has the
default user interface or
the extended user
interface.
Retrieves from a combo
box the scrollable width,
in pixels, by which the
list box can be scrolled
horizontally. This is
applicable only if the list
box has a horizontal
scroll bar.
Retrieves the
application-supplied
32-bit value associated
with the specified item in
the combo box.
Determines the height of
list items or the selection
field in a combo box.
Retrieves a string from
the list of a combo box.
Retrieves the length, in
characters, of a string in
the list of a combo box.
continues
Page 170
Table 7.15
Combo Box Control Messages, continued
Message
CB_GETLOCALE
Description
Retrieves the current locale of the
combo box. The locale is used to
determine the correct sorting order of
displayed text for combo boxes with
the CBS_SORT style and text added
by using the CB_ADDSTRING
message.
CB_SETCURSEL
CB_SETDROPPEDWIDTH
Description
Selects a string in the list of
a combo box. If necessary,
the list scrolls the string
into view. The text in the
edit control of the combo
box changes to reflect the
new selection, and any
previous selection in the list
is removed.
Sets the maximum
acceptable width, in pixels,
of the list box
of a combo box with the
CBS_DROPDOWN or
CBS_DROPDOWNLIST
style.
Description
Description
Indicates the list box part of the
combo box has been closed.
Indicates the list box part of the
combo box is about to be made
visible.
Keyword
Brief
Full
Advanced
Search
Search Tips
view control has four possible views: icon, small icon, list, and report. The report view makes it convenient to produce
multicolumn list boxes. The TravelManager application uses a list view control in the Itinerary-Air dialog box and in the
Expenses dialog box (see Figure 7.2 and Figure 7.3).
Figure 7.2
Itinerary-Air dialog box.
Figure 7.3
Expenses dialog box.
Description
Specifies that items are
LVS_ALIGNLEFT
left-aligned in icon and small
icon view.
Specifies that items are aligned
with the top of the list view
LVS_ALIGNTOP
control in icon and small icon
view.
Specifies that icons are
LVS_AUTOARRANGE
automatically kept arranged in
icon and small icon view.
Specifies that item icons look
LVS_BUTTON
like buttons in icon view.
Permits item text to be edited in
place. The parent window must
LVS_EDITLABELS
process the
LVN_ENDLABELEDIT
notification message.
LVS_ICON
Specifies icon view.
LVS_LIST
Specifies list view.
Specifies that a column header
is not displayed in report view.
LVS_NOCOLUMNHEADER
By default, columns have
headers in report view.
Displays item text on a single
line in icon view. By default,
LVS_NOLABELWRAP
item text may wrap in icon
view.
Disables scrolling. All items
LVS_NOSCROLL
must be within the client area.
Specifies that column headers
do not work like buttons. This
style is useful if clicking a
LVS_NOSORTHEADER
column header in report view
does not carry out an action,
such as sorting.
Page 176
Table 7.17
Description
Enables the owner window to
paint items in report view. The
list view control sends a
WM_DRAWITEM message to
paint each item; it does not send
LVS_OWNERDRAWFIXED
separate messages for each
subitem. The itemData member
of the DRAWITEMSTRUCT
structure contains the item data
for the specified list view item.
LVS_REPORT
Specifies report view.
Specifies that the control does
not take ownership of the image
lists assigned to it; that is, it
does not destroy the image lists
LVS_SHAREIMAGELISTS
when it is destroyed. This style
enables the same image lists to
be used with multiple list view
controls.
Always shows the selection
LVS_SHOWSELALWAYS highlight, even if the control is
not activated.
Enables only one item at a time
LVS_SINGLESEL
to be selected. By default,
multiple items may be selected.
LVS_SMALLICON
Specifies small icon view.
Sorts items based on item text in
LVS_SORTASCENDING
ascending order.
Sorts items based on item text in
LVS_SORTDESCENDING
descending order.
List View Control Messages and Functions
An application sends messages to a list view control to alter its appearance, add or change items and columns, and so on. Each
message has a corresponding function (macro) that can be used instead of sending the message explicitly.
Page 177
The TravelManager application uses many ListView functions, including: ListView_InsertColumn, ListView_GetItemCount,
0, &lvc);
1, &lvc);
2, &lvc);
3, &lvc);
4, &lvc);
5, &lvc);
6, &lvc);
13",L"456",L"Indianapolis",L"Atlanta",L"1:15pm",L"2:30pm",L"24A"},
{L"1/13",L"1034",L"Atlanta",L"Seattle",L"3:20pm",L"4:42pm",
L"12D"},
{L"1/18",L"1113",L"Seattle",L"Atlanta",L"9:05pm",L"3:18pm",
L"8F"},
{L"1/18",L"1034",L"Atlanta",L"Indianapolis",L"4:55pm",
L"7:00pm",L"10C"}
};
LV_ITEM lvi;
lvi.mask = LVIF_TEXT;
lvi.iSubItem = 0;
int i,k;
for (i=0; i<4; i++)
{
lvi.iItem = i;
lvi.pszText = szAirData[i][0];
lvi.cchTextMax = 6;
ListView_InsertItem(hwndLV, &lvi);
for (k=1; k<7; k++)
{
ListView_SetItemText(hwndLV, i, k, szAirData[i][k]);
}
}
Table 7.18 shows the available list view messages and their corresponding macros.
Table 7.18
List View Control Messages
Message
Function
Description
Arranges the items in
LVM_ARRANGE ListView_Arrange large icon view based on
the flag's set.
Page 179
Message
Function
Description
Creates a
drag image
LVM_CREATEDRAGIMAGE ListView_CreateDragImage for the
specified
item.
Removes
all items
LVM_DELETEALLITEMS ListView_DeleteAllItems from a list
view
window.
Removes a
column
LVM_DELETECOLUMN
ListView_DeleteColumn from a list
view
window.
Removes a
single item
LVM_DELETEITEM
ListView_DeleteItem
from a list
view
window.
Begins
in-place
editing of
an item's
text label.
LVM_EDITLABEL
ListView_EditLabel
This
message
selects and
sets the
focus to
the item.
LVM_ENSUREVISIBLE
ListView_EnsureVisible
Ensures
that an
item is
entirely or
partially
visible by
scrolling
the list
view
window if
necessary.
continues
Page 180
Table 7.18
List View Control Messages, continued
Message
Function
Description
Searches
for an item
LVM_FINDITEM
ListView_FindItem
in a list
view
control.
Retrieves
the
background
LVM_GETBKCOLOR
ListView_GetBkColor
color of the
list view
window.
Retrieves
the
callback
LVM_GETCALLBACKMASK ListView_GetCallbackMask
mask for a
list view
window.
Retrieves
the
attributes
LVM_GETCOLUMN
ListView_GetColumn
of a
specified
column.
Retrieves
the width
of a
LVM_GETCOLUMNWIDTH ListView_GetColumnWidth column in
list view or
details
view.
Calculates
the number
of items
that can fit
vertically
LVM_GETCOUNTPERPAGE ListView_GetCountPerPage
in the
visible area
in list view
or details
view.
Page 181
Message
Function
Description
Retrieves
the handle
of the edit
window
LVM_GETEDITCONTROL ListView_GetEditControl
used to edit
an item's
text label
in place.
Retrieves
the handle
of an
LVM_GETIMAGELIST
ListView_GetImageList image list
used for
drawing
items.
Retrieves
the
LVM_GETITEM
ListView_GetItem
attributes
of an item.
Retrieves
the number
LVM_GETITEMCOUNT ListView_GetItemCount of items in
a list view
control.
Retrieves
the
position of
an item in
LVM_GETITEMPOSITION ListView_GetItemPosition
large icon
view or
small icon
view.
Retrieves
the
bounding
rectangle
LVM_GETITEMRECT
ListView_GetItemRect
for an item
in the
current
view.
Retrieves
LVM_GETITEMSTATE
ListView_GetItemState the state of
an item.
continues
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
Table 7.18
List View Control Messages, continued
Message
Function
LVM_GETITEMTEXT
ListView_GetItemText
LVM_GETNEXTITEM
ListView_GetNextItem
Description
Retrieves
the text of
an item or
a subitem.
Searches
for the next
item,
starting
from a
specified
item.
Retrieves
the list
view origin
point,
LVM_GETORIGIN
ListView_GetOrigin
which is
needed for
setting the
item
position.
Retrieves
the
minimum
column
width
necessary
to display
the given
string. The
returned
width takes
LVM_GETSTRINGWIDTH ListView_GetStringWidth the current
font and
column
margins of
the list
view
control
(but not the
width of a
small icon)
into
account.
Page 183
Message
Function
Description
Retrieves
the
background
LVM_GETTEXTBKCOLOR ListView_GetTextBkColor text color
in a list
view
window.
LVM_GETTEXTCOLOR
ListView_GetTextColor
LVM_GETTOPINDEX
ListView_GetTopIndex
LVM_GETVIEWRECT
ListView_GetViewRect
LVM_HITTEST
ListView_HitTest
LVM_INSERTCOLUMN
ListView_InsertColumn
LVM_INSERTITEM
ListView_InsertItem
Retrieves
the color of
the text in a
list view
window.
Retrieves
the index
of the first
visible item
in a list
view
window.
Retrieves
the
bounding
rectangle
of all items
in large
icon view.
Determines
which item
is at a
specified
position in
a list view
window.
Inserts a
new
column in
a list view
window.
Inserts a
new item
in a list
view
window.
continues
Page 184
Table 7.18
Function
Description
Forces a
redraw of a
range of
LVM_REDRAWITEMS
ListView_RedrawItems
items in a
list view
control.
Scrolls the
contents of
LVM_SCROLL
ListView_Scroll
a list view
window.
Sets the
background
LVM_SETBKCOLOR
ListView_SetBkColor
color of a
list view
window.
Sets the
callback
LVM_SETCALLBACKMASK ListView_SetCallbackMask mask for a
list view
window.
Sets the
attributes
of a
LVM_SETCOLUMN
ListView_SetColumn
column in
a list view
control.
Sets the
width of a
column in
LVM_SETCOLUMNWIDTH ListView_SetColumnWidth
details
view or list
view.
LVM_SETIMAGELIST
ListView_SetImageList
Sets the
image list
used for
drawing
items in a
list view
control.
Page 185
Message
Description
Sets an item's
LVM_SETITEM
ListView_SetItem
attributes.
Sets the item count
LVM_SETITEMCOUNT
ListView_SetItemCount of a list view
control.
Sets the position of
an item in large
icon view or small
LVM_SETITEMPOSITION ListView_SetItemPosition
icon view relative
to the list view
rectangle.
Sets the state of an
LVM_SETITEMSTATE
ListView_SetItemState
item.
Sets the text of an
LVM_SETITEMTEXT
ListView_SetItemText
item or a subitem.
Sets the
background text
LVM_SETTEXTBKCOLOR ListView_SetTextBkColor
color in a list view
window.
Sets the text color
LVM_SETTEXTCOLOR
ListView_SetTextColor in a list view
window.
Sorts items in a list
view control, using
an
LVM_SORTITEMS
ListView_SortItems
application-defined
comparison
function.
LVM_UPDATE
ListView_Update
Updates an item.
Page 186
Function
Page 187
}
else if (pNMHdr->code == NM_DBLCLK)
{
int iCurSel = ListView_GetNextItem (hwndLV,
_1, LVNI_SELECTED);
if (iCurSel != _1)
{
ExpAddEditDlg * pDlg;
pDlg = new ExpAddEditDlg(m_pMainWindow, TRUE, hwndLV);
pDlg->Create();
}
}
}
return TRUE;
}
The possible notifications from the list view control are described in Table 7.19.
Table 7.19
List View Control Notifications
Notification
Description
Indicates that a drag-and-drop
LVN_BEGINDRAG
operation involving the left mouse
button is being initiated.
Indicates the start of label editing
LVN_BEGINLABELEDIT
for an item.
Indicates that a drag-and-drop
LVN_BEGINRDRAG
operation involving the right
mouse button is being initiated.
Indicates that a column was
LVN_COLUMNCLICK
clicked.
Indicates that all items in the
LVN_DELETEALLITEMS
control were deleted.
LVN_DELETEITEM
Indicates that an item was deleted.
continues
Page 188
Table 7.19
List View Control Notifications, continued
Notification
Description
Indicates the end of default
processing for a drag-and-drop
LVN_ENDDRAG
operation involving the left mouse
button.
Indicates the end of label editing for
LVN_ENDLABELEDIT
an item.
Indicates the end of default
processing for a drag-and-drop
LVN_ENDRDRAG
operation involving the right mouse
button.
Requests a list view control's parent
LVN_GETDISPINFO
window to provide information
needed to display or sort an item.
Indicates that a new item was
LVN_INSERTITEM
inserted.
LVN_ITEMCHANGED Indicates that an item has changed.
LVN_ITEMCHANGING Indicates that an item is changing.
Indicates that a key has been
LVN_KEYDOWN
pressed.
Notifies a list view control's parent
LVN_SETDISPINFO
window that it must update the
information it maintains for an item.
Keyword
Brief
Full
Advanced
Search
Search Tips
Figure 7.4
TravelManager's Tree control.
Table 7.20
Tree View Control Styles
Style
Description
Prevents the tree view control
from sending
TVS_DISABLEDRAGDROP
TVN_BEGINDRAG
notification messages.
Enables the user to edit the
TVS_EDITLABELS
labels of tree view items.
Displays plus (+) and minus (-)
buttons next to parent items.
The user clicks the buttons to
expand or collapse a parent
TVS_HASBUTTONS
item's list of child items. To
include buttons with items at the
root of the tree view,
TVS_LINESATROOT must
also be specified.
Uses lines to show the hierarchy
TVS_HASLINES
of items.
Uses lines to link items at the
root of the tree view control.
TVS_LINESATROOT
This value is ignored if
TVS_HASLINES is not also
specified.
Uses the system highlight colors
TVS_SHOWSELALWAYS
to draw the selected item.
Page 190
Tree View Control Messages and Functions
An application sends messages to a tree view control to alter its appearance, add or change items, and so on. Each
message has a corresponding function (macro) that can be used instead of sending the message explicitly.
In the FlightInfoDlg::WMInitDialog, the TravelManager application creates the items in the tree using the
TreeView_InsertItem function. The data inserted into the tree is hard-coded here, but would eventually come from the
database.
TV_INSERTSTRUCT TreeCtrlItem;
// lParam can hold any value we want; we'll use 0 to mean the node
// has children and non-zero to mean it is a leaf node.
TreeCtrlItem.hParent = TVI_ROOT;
TreeCtrlItem.hInsertAfter = TVI_LAST;
TreeCtrlItem.item.mask = TVIF_TEXT | TVIF_PARAM;
TreeCtrlItem.item.pszText = L"From Indianapolis";
TreeCtrlItem.item.lParam = 0;
HTREEITEM hTreeItem1 = TreeView_InsertItem(hwndTree, &TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem1;
TreeCtrlItem.item.pszText = L"To New York";
TreeCtrlItem.item.lParam = 0;
HTREEITEM hTreeItem2= TreeView_InsertItem(hwndTree, &TreeCtrlItem);
TreeCtrlItem.hParent = hTreeItem2;
TreeCtrlItem.item.pszText = L"10:00 am";
TreeCtrlItem.item.lParam = 1;
TreeView_InsertItem(hwndTree, &TreeCtrlItem);
... etc. ...
Table 7.21 shows the available tree view messages and their corresponding macros.
Page 191
Table 7.21
Tree View Control Messages
Message
Function
Description
Creates a
drag image
TVM_CREATEDRAGIMAGE TreeView_CreateDragImage for the
specified
item.
Deletes all
items in a
TVM_DELETEITEM
TreeView_DeleteAllItems
tree view
window.
Deletes a
specified
TVM_DELETEITEM
TreeView_DeleteItem
item from
a tree view
window.
Begins
in-place
editing of
an item's
text label.
The text is
replaced by
a
single-line
TVM_EDITLABEL
TreeView_EditLabel
edit
window
containing
the original
text in a
selected
and
focused
state.
TVM_ENSUREVISIBLE
TreeView_EnsureVisible
Ensures
that an
item is
visible and
expands
the parent
item or
scrolls the
tree view
window if
necessary.
continues
Page 192
Table 7.21
Tree View Control Messages, continued
Message
Description
Expands or
collapses the
list of child
TVM_EXPAND
TreeView_Expand
items
associated
with a parent
item.
Retrieves the
child of a
TVM_GETNEXTITEM
TreeView_GetChild
specified tree
view item.
Returns the
number of
TVM_GETCOUNT
TreeView_GetCount
items in a tree
view window.
Retrieves the
target of a
TVM_GETDROPHILITE TreeView_GetDrop-Hilight
drag-and-drop
operation.
Retrieves the
handle of the
edit control
being used
TVM_GETEDITCONTROL TreeView_GetEditControl
for in-place
editing of an
item's text
label.
Retrieves the
first visible
TVM_GETNEXTITEM
TreeView_GetFirstVisible
item of a tree
view control.
Retrieves the
handle of the
image list
TVM_GETIMAGELIST
TreeView_GetImageList
associated
with a tree
view window.
Page 193
Tree View Control Messages
Function
Retrieves
the amount,
in pixels,
that child
TVM_GETINDENT
TreeView_GetIndent
items are
indented
relative to
their parent
item.
Retrieves
information
TVM_GETITEM
TreeView_GetItem
about an
item.
Retrieves
the
bounding
rectangle
TVM_GETITEMRECT TreeView_GetItemRect
and
visibility
state of an
item.
Retrieves
the next
item
TVM_GETNEXTITEM TreeView_GetNextItem
matches a
specified
relationship.
Retrieves
the next
TVM_GETNEXTITEM TreeView_GetNextSibling
sibling of
an item.
Retrieves
the next
visible item
following
TVM_GETNEXTITEM TreeView_GetNextVisible
the
specified
tree view
item.
Retrieves
TVM_GETNEXTITEM TreeView_GetParent
the parent
of an item.
Retrieves
the previous
TVM_GETNEXTITEM TreeView_GetPrevSibling
sibling of
an item.
continues
Page 194
Table 7.21
Tree View Control Messages, continued
Message
TVM_GETNEXTITEM
Function
Description
Retrieves the
first visible
item
TreeView_GetPrevVisible
preceding the
specified tree
view item.
Retrieves the
root of an
item.
Retrieves the
TVM_GETNEXTITEM
TreeView_GetSelection
currently
selected item.
Retrieves the
count of
items that
TVM_GETVISIBLECOUNT TreeView_GetVisibleCount
will fit into
the tree view
window.
Retrieves the
tree view
item that
occupies the
specified
TVM_HITTEST
TreeView_HitTest
point. This
message is
generally
used for
drag-and-drop
operations.
Inserts a new
TVM_INSERTITEM
TreeView_InsertItem
item in a tree
view window.
TVM_GETNEXTITEM
TreeView_GetRoot
Page 195
Message
Function
Description
Selects, scrolls into
TVM_SELECTITEM
TreeView_Select
view, or redraws
an item.
Selects an item as
TVM_SELECTITEM
TreeView_SelectDropTarget
the drop target.
TVM_SELECTITEM
TreeView_SelectItem
Selects an item.
Sets the image list
for a tree view
TVM_SETIMAGELIST
TreeView_SetImageList
window and
redraws it.
Sets the amount of
TVM_SETINDENT
TreeView_SetIndent
indention for a
child item.
Sets the attributes
TVM_SETITEM
TreeView_SetItem
of an item.
Sorts the child
TVM_SORTCHILDREN
TreeView_SortChildren
items of a given
parent item.
Sorts items using
an
TVM_SORTCHILDRENCB TreeView_SortChildrenCB application-defined
comparison
function.
Page 196
Tree View Control Notifications
A tree view control sends the following WM_NOTIFY notification messages to its parent window. In the Alternate
Flight Lookup dialog box, the TravelManager application processes the TVN_SELCHANGED notification and sets the
static text accordingly. (The text will eventually come from the database rather than be hard-coded.)
LRESULT FlightInfoDlg::WMNotify( HWND hWnd,
LPARAM lParam )
{
NM_TREEVIEW * pnmh = (NM_TREEVIEW *) lParam;
switch (pnmh->hdr.code)
{
case TVN_SELCHANGED:
{
if (pnmh->itemNew.lParam !=
{
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
}
else
{
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
0)
IDC_FROM, L"Seattle");
IDC_TO, L"Indianapolis");
IDC_DEPARTS, L"8:20 am");
IDC_ARRIVES, L"4:45 pm");
IDC_AIRLINE, L"Delta");
IDC_CONNECTION, L"Atlanta");
IDC_LAYOVER, L"1:10");
Keyword
Brief
Full
Advanced
Search
Search Tips
L"<not selected>");
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
SetDlgItemText(hWnd,
}
}
break;
}
return 0;
The possible notifications from the tree view control are listed in Table 7.22.
Table 7.22
Tree View Control Notifications
Notification
Description
Indicates that a drag-and-drop
TVN_BEGINDRAG
operation involving the left mouse
button is being initiated.
Indicates the start of label editing
TVN_BEGINLABELEDIT
for an item.
Description
Indicates that a parent item's list of
TVN_ITEMEXPANDING child items is about to expand or
collapse.
Indicates that the user pressed a
TVN_KEYDOWN
key and the tree view control has
the input focus.
Indicates that the selection has
TVN_SELCHANGED
changed from one item to another.
Indicates that the selection is about
TVN_SELCHANGING
to change from one item to another.
Notifies a tree view control's parent
window that it must update the
TVN_SETDISPINFO
information it maintains about an
item.
Tab Control
A tab control is similar to a set of notebook dividers: It separates topics or sections of information and helps you locate a
particular topic or section easily. A tab control is also helpful for dividing information when there's not enough screen
real-estate. The TravelManager uses a tab control to divide the itinerary information up into three parts: Air, Car, Hotel (see
Figure 7.5).
Figure 7.5
Tab control.
Page 199
In the ItineraryView::Create function, the tab control is created using CreateWindow function. The size of the tab control is
determined by getting the client size of the main window and then accounting for the size of the command bar.
BOOL ItineraryView::Create()
{
RECT rect;
int iFlags = WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_CLIPSIBLINGS|
TCS_MULTILINE|TCS_VERTICAL;
GetClientRect(m_pMainWindow->m_hWnd, &rect);
rect.top += CommandBar_Height(m_pMainWindow->m_hwndCB);
HWND hwndTab = CreateWindow(WC_TABCONTROL, L"",iFlags,
rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, m_pMainWindow->m_hWnd,
(HMENU)12345, m_pMainWindow->m_pApp->m_hInst, NULL);
m_hWnd = hwndTab;
Tab Control Styles
The window styles listed in Table 7.23 are specific to tab controls.
Table 7.23
Tab Control Styles
Style
TCS_BUTTONS
Description
Specifies that tabs appear as buttons and
no border is drawn around the display
area.
Description
Specifies that the tab
TCS_FOCUSNEVER
control never receives the
input focus.
Specifies that tabs receive
TCS_FOCUSONBUTTONDOWN the input focus when
clicked.
Aligns icons with the left
edge of each fixed-width
TCS_FORCEICONLEFT
tab. This style can only be
used with the
TCS_FIXEDWIDTH style.
Aligns labels with the left
edge of each fixed-width
tab; that is, it displays the
label immediately to the
right of the icon instead of
TCS_FORCELABELLEFT
centering it. This style can
only be used with the
TCS_FIXEDWIDTH style,
and it implies the
TCS_FORCEICONLEFT
style.
Displays multiple rows of
TCS_MULTILINE
tabs, if necessary, so all
tabs are visible at once.
Specifies that the parent
TCS_OWNERDRAWFIXED
window is responsible for
drawing tabs.
TCS_RAGGEDRIGHT
TCS_RIGHTJUSTIFY
TCS_SINGLELINE
Page 201
Style
Description
Specifies that tabs appear as tabs and that a
TCS_TABS
border is drawn around the display area. This
style is the default.
Specifies that the tab control has a tooltip
TCS_TOOLTIPS
control associated with it.
Tab Control Messages and Functions
An application sends messages to a tree view control for various reasons: to alter its appearance, add or change items, and so
on. Each message has a corresponding function (macro) that can be used instead of sending the message explicitly.
After creating the tab control window, the TravelManager application uses a variety of tab control functions to create the
individual pages (tabs). The tabs are positioned vertically along the right side rather than the top due to the vertical real estate
space on Windows CE. Although the tab control is not able to rotate the text for the tab, that limitation can be overcome by
creating the vertical text as a bitmap and then using the bitmap for the tab. In order to put images on a tab, they must be stored
in an image list.
HBITMAP
hbitmap;
HIMAGELIST hTabImage = ImageList_Create(15, 38, ILC_COLOR, 3, 0);
// Load the icons and add them to the image list
hbitmap = LoadBitmap(m_pMainWindow->m_pApp->m_hInst, L"IDB_AIR");
ImageList_Add(hTabImage, hbitmap, NULL);
DeleteObject(hbitmap);
hbitmap = LoadBitmap(m_pMainWindow->m_pApp->m_hInst, L"IDB_CAR");
ImageList_Add(hTabImage, hbitmap, NULL);
DeleteObject(hbitmap);
hbitmap = LoadBitmap(m_pMainWindow->m_pApp->m_hInst, L"IDB_HOTEL");
ImageList_Add(hTabImage, hbitmap, NULL);
DeleteObject(hbitmap);
TabCtrl_SetPadding(hwndTab,5,5);
TabCtrl_SetImageList(hwndTab, hTabImage);
Page 202
After loading the images into the image list, the image for a particular tab control is specified in the iImage member of the
TC_ITEM structure. Each of the dialog boxes that will be used as the pages for the tab control are also created. All the dialog
boxes are created now enabling a pointer to the dialog box to be stored in the tab control (the lParam member).
TC_ITEM item;
HWND dlg, dlg2, dlg3;
item.cchTextMax= 32;
item.mask
= (UINT)TCIF_IMAGE | TCIF_PARAM;
item.iImage = 0;
dlg = CreateDialogParam( m_pMainWindow->m_pApp->m_hInst, L"ITINERARY_AIR", hwndTab,
DlgProc, (LPARAM)this );
g_ModelessDlg = dlg;
item.lParam = (LPARAM)dlg;
TabCtrl_InsertItem (hwndTab, 0, (TC_ITEM FAR*)&item);
item.iImage = 1;
dlg2 = CreateDialogParam( m_pMainWindow->m_pApp->m_hInst, L"ITINERARY_CAR", hwndTab,
DlgProc, (LPARAM)this );
item.lParam = (LPARAM)dlg2;
TabCtrl_InsertItem (hwndTab, 1, (TC_ITEM FAR*)&item);
item.iImage = 2;
dlg3 = CreateDialogParam( m_pMainWindow->m_pApp->m_hInst, L"ITINERARY_HOTEL", hwndTab
DlgProc, (LPARAM)this );
item.lParam = (LPARAM)dlg3;
TabCtrl_InsertItem (hwndTab, 2, (TC_ITEM FAR*)&item);
Finally, you determine the size of the client area for the tab control and adjust the size of each of the pages (dialog boxes) to
fit, as follows:
TabCtrl_AdjustRect(hwndTab, FALSE, &rect);
MoveWindow(dlg, rect.left, 2, rect.right-rect.left, rect.bottom-rect.top, TRUE);
MoveWindow(dlg2, rect.left, 2, rect.right-rect.left, rect.bottom-rect.top, FALSE);
Keyword
Brief
Full
Advanced
Search
Search Tips
ShowWindow(dlg2, SW_HIDE);
MoveWindow(dlg3, rect.left, 2, rect.right-rect.left, rect.bottom-rect.top, FALSE);
ShowWindow(dlg3, SW_HIDE);
Table 7.24 shows the available tab control messages and their corresponding macros.
Table 7.24
Tab Control Messages
Message
Function
TCM_ADJUSTRECT
TabCtrl_AdjustRect
Description
Calculates
a tab
control's
display
area given
a window
rectangle
or
calculates
the
window
rectangle
that would
correspond
to a
specified
display
area.
Removes
all items
TCM_DELETEALLITEMS TabCtrl_DeleteAllItems
from a tab
control.
Removes
an item
TCM_DELETEITEM
TabCtrl_DeleteItem
from a tab
control.
Returns the
index of
the item
TCM_GETCURFOCUS
TabCtrl_GetCurFocus
that has the
focus in a
tab control.
Determines
the
currently
TCM_GETCURSEL
TabCtrl_GetCurSel
selected
tab in a tab
control.
Retrieves
the image
list
TCM_GETIMAGELIST
TabCtrl_GetImageList
associated
with a tab
control.
continues
Page 204
Table 7.24
Tab Control Messages, continued
Message
Function
Description
Retrieves
information
TCM_GETITEM
TabCtrl_GetItem
about a tab
in a tab
control.
Retrieves
the number
TCM_GETITEMCOUNT TabCtrl_GetItemCount of tabs in
the tab
control.
Retrieves
the
bounding
TCM_GETITEMRECT TabCtrl_GetItemRect
rectangle
for a tab in a
tab control.
Retrieves
the current
number of
TCM_GETROWCOUNT TabCtrl_GetRowCount
rows of tabs
in a tab
control.
Retrieves
the handle
to the
tooltip
TCM_GETTOOLTIPS TabCtrl_GetToolTips
control
associated
with a tab
control.
Determines
which tab, if
any, is at a
TCM_HITTEST
TabCtrl_HitTest
specified
screen
position.
Inserts a
TCM_INSERTITEM
TabCtrl_InsertItem
new tab in a
tab control.
Removes an
image from
TCM_REMOVEIMAGE TabCtrl_RemoveImage a tab
control's
image list.
Sets the
focus to a
TCM_SETCURFOCUS TabCtrl_SetCurFocus specified
tab in a tab
control.
Selects a tab
TCM_SETCURSEL
TabCtrl_SetCurSel
in a tab
control.
Page 205
Message
Function
Description
Assigns an image
TCM_SETIMAGELIST TabCtrl_SetImageList
list to a tab control.
Sets some or all of
TCM_SETITEM
TabCtrl_SetItem
a tab's attributes.
Sets the number of
bytes per tab
reserved for
TCM_SETITEMEXTRA TabCtrl_SetItemExtra
application-defined
data in a tab
control.
Sets the width and
height of tabs in a
TCM_SETITEMSIZE TabCtrl_SetItemSize fixed-width or
owner-drawn tab
control.
Sets the amount of
space (padding)
TCM_SETPADDING TabCtrl_SetPadding around each tab's
icon and label in a
tab control.
Assigns a tooltip
TCM_SETTOOLTIPS TabCtrl_SetToolTips control to a tab
control.
A tree view control sends the following notification messages to its parent window in the form of WM_NOTIFY messages.
The Travel Manager application handles the TCN_SELCHANGING and TCN_SELCHANGE notifications to hide and
display the appropriate dialog boxes.
LRESULT MainWindow::WMNotify( HWND hWnd,
{
TC_ITEM tcItem;
int iTab;
Page 206
}
The possible tree control notifications are listed in Table 7.25.
Table 7.25
Tree View Control Notifications
Notification
TCN_KEYDOWN
Description
Indicates that a key has been pressed.
Indicates that the currently selected
TCN_SELCHANGE
tab has changed.
Indicates that the currently selected
TCN_SELCHANGING
tab is about to change.
Page 207
TravelManager ApplicationChapter 7
Quite a lot has been added to the TravelManager application since the last chapter. Most of the user interface elements are now
in place in the application. New C++ classes created in this chapter include the following:
ItineraryView. The class that encapsulates the components of the itinerary view, such as the tab control and its pages.
ExpensesView. The class that encapsulates the view dealing with listing, adding, editing and deleting of expenses.
NotesView. The class for our view that enables the entry of notes (and eventually the saving of the notes).
ExpAddEditDlg. The class that permits the entry of new expenses and the editing of current expenses.
Although the visible interface is nearly complete, most of the data that is displayed is just hard-coded static data. In the coming
chapters, the capability to get that data from the database will be added.
For the sake of space, the entire TravelManager application is not relisted here. The accompanying CD-ROM contains the
source code and project file changes to the TravelManager application developed in each chapter. See Appendix A, "Getting
Started with the CD-ROM," for information on accessing the source code on the CD-ROM.
Page 208
Previous | Table of Contents | Next
CHAPTER 8
Keyboard Input
In Windows CE, keyboard input conventions are similar to those for other versions of Windows. This similarity exists for
both the physical layout of the keyboard and for the way Windows CE notifies applications of keyboard events.
Keyboard Hardware
Although Windows CE may eventually support devices without keyboards, the hardware requirements for the initial
Handheld PCs define a basic keyboard layout that is as close to the PC keyboard as possible. Due to the obvious space
constraints however, there are some common keys that are not supported, including Insert, Scroll Lock, Pause, Num Lock,
Print Screen, and all the function keys. Windows CE applications should avoid functionality that requires these keys.
Tip
In Windows CE, Shift+Backspace is equivalent to the
Delete key.
Keyboard Functionality in Windows CE
With the exception of a few unsupported keyboard-related API functions, the way a Windows CE program interacts with
the keyboard is identical to programs under other versions of Windows. Usually that means applications do not monitor
direct keyboard input at all.
Similarly, Windows CE, like other Windows versions, handles most keyboard functionality itself. When a user uses the
keyboard, an application is interested more in the effect of the keystrokes. For instance, if the user selects an option on a
menu, Windows CE notifies the application that a menu option was selected; it doesn't determine how the selection was
made (the application shouldn't care whether the menu option was selected using the keyboard or the stylus/mouse).
There are some instances, however, where an application does want
to monitor the actual keystrokes from the keyboard. As in Win32, all applications essentially share the keyboard, and the
operating system
Page 211
delivers keyboard messages to the correct window. The window that receives the keyboard message is the window with the
input focus, which is either the active window or a child of the active window.
Most child windows have controls such as push buttons, edit controls, or list boxes. When a child window has input focus,
then the active window is the control's parent (for example, the dialog box). A window can determine when it has focus by
trapping the WM_SETFOCUS and WM_KILLFOCUS messages.
Applications receive messages about keyboard events through both keystroke and character messages. The keystroke
messages correspond directly to the pressing of keys on the keyboard; Windows CE interprets those keystrokes and, if
applicable, delivers additional character messages. For instance, pressing and releasing the "A" key generates two keystroke
messages (one for the key going down; one for the key going up). Windows CE then assists by interpreting the character for
that key press. For instance, normally, pressing the A key would result in a character of lowercase a. However, depending
on the status of the Shift, Ctrl, and Caps Lock keys, that A key could result in an uppercase A or perhaps a special character.
When a key is pressed, Windows CE delivers either a WM_KEYDOWN or a WM_SYSKEYDOWN message to the
window with input focus. When the key is released, Windows CE delivers either a WM_KEYUP or WM_SYSKEYUP
message. The SYS messages refer to system keystroke messages. System keystrokes messages are usually generated for
keys pressed in combination with the Alt key.
The character messages that Windows CE delivers are WM_CHAR, WM_SYSCHAR, WM_DEADCHAR, and
WM_SYSDEADCHAR. Dead character messages are used with non-U.S. keyboards in which certain keys are defined to
add a diacritic to a letter.
Keyboard Functions
Table 8.1 lists all the Win32 keyboard-related functions and provides a description of their functionality as supported by
Windows CE.
Page 212
Table 8.1
Keyboard Functions
Function
Description
ActivateKeyboardLayout Not supported for Windows CE.
Enables or disables mouse and keyEnableWindow
board input to the specified window
or control.
Retrieves the window handle of the
GetActiveWindow
active window.
Determines whether a key is up or
GetAsyncKeyState
down at the time the function is
called.
Retrieves the handle of the
GetFocus
keyboard focus window.
GetKeyboardLayoutName Not supported for Windows CE.
GetKeyboardState
Not supported for Windows CE.
GetKeyNameText
Not supported for Windows CE.
Retrieves the status of the specified
GetKeyState
virtual key.
Determines whether the specified
IsWindowEnabled
window is enabled for touch screen
input and keyboard input.
keybd_event
Synthesizes a keystroke.
LoadKeyboardLayout
Not supported for Windows CE.
Translates (maps) a virtual-key
MapVirtualKey
code into a scan code or character
value.
OemKeyScan
Not supported for Windows CE.
RegisterHotKey
Not supported for Windows CE.
Makes the specified window the
SetActiveWindow
active window.
Page 213
Function
Description
Keyboard Messages
Table 8.2 lists the Win32 keyboard messages and a description of their Windows CE functionality.
Table 8.2
Keyboard Messages
Message
Description
Sent when a window is being activated or
WM_ACTIVATE
deactivated.
Sent to the window with the keyboard
focus when a WM_KEYDOWN message
WM_CHAR
is translated by the TranslateMessage
function. WM_CHAR contains the
character code of the key that was pressed.
Sent to the window with the keyboard
focus when a WM_KEYUP message is
WM_DEADCHAR translated by the TranslateMessage
function. WM_DEADCHAR specifies a
character code generated by a dead key.
continues
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
Page 214
Table 8.2
Keyboard Messages, continued
Message
WM_HOTKEY
WM_KEYDOWN
WM_KEYUP
WM_KILLFOCUS
WM_SETFOCUS
WM_SYSCHAR
Description
Not supported for Windows CE.
Sent to the window with the keyboard
focus when a nonsystem key is
pressed.
Sent to the window with the keyboard
focus when a nonsystem key is
released.
Sent to a window immediately before
it loses the keyboard focus.
Sent to a window after it has gained
the keyboard focus.
Sent to the window with the keyboard
focus when a WM_SYSKEYDOWN
message is translated by the
TranslateMessage function. It
specifies the character code of a
system character key (a character key
that is pressed while the Alt key is
down).
Note
In the previous code, the calls to InvalidateRect and UpdateWindow will cause the window to be repainted,
thereby clearing the contents of the window.
Page 216
Stylus Input
One apparent difference between Windows CE and other versions of Windows is the absence of a familiar staple of Windows:
the mouse. Although original versions of Windows never required a mouse, the mouse has certainly become a standard input
device. Window CE, on the other hand, achieves similar functionality through the addition of a touch screen and stylus.
In Windows CE, the stylus is used to perform the actions previously associated with a mouse: clicking, double-clicking, and
dragging. In pen/stylus notation, those actions would be referred to as tapping, double-tapping, and dragging. Win32 enables
those actions to be initiated by one of three buttons on the mouse (although the mouse usually only has two buttons). Windows
CE obviously can't support three buttons, but it does try to emulate the most common "right-button click" when the user taps
on the screen while holding down the Alt key.
Stylus Functionality in Windows CE
Although the methods for generating the mouse/stylus events are quite different between Windows CE and other versions of
Windows, the way applications interpret those events is quite similar. Windows CE uses the same WM_LBUTTONDOWN,
WM_LBUTTONUP, and WM_LBUTTONDBLCLK as Win32. These messages signal when the user has pressed on the touch
screen, let up from the touch screen, or double-tapped on the screen, respectively.
As previously stated, Windows CE enables the same functionality as right-clicking by using the Alt key when tapping.
However, Windows CE does not interpret those events and deliver any RBUTTON messages. Instead, an application should
use the GetAsyncKeyState when processing the WM_LBUTTONDOWN message to determine if the user is simulating a
right-button click.
Another difference in Windows CE is cursor support. Because there is no mouse cursor on the Windows CE display, cursor
support is greatly reduced. The only cursor function supported is SetCursor, and even it is
Page 217
very constrained. The only cursor support available to an application is the functionality to display the "wait cursor."
Like Win32, stylus/mouse messages go to the window in which the user clicks. It is possible for an application to "capture" the
stylus/mouse so that the application receives messages even when the stylus/mouse is used outside the window. An application
can use the SetCapture and ReleaseCapture functions to manipulate capture of te stylus/mouse messages.
Win32 applications can receive many non-client area mouse messages. On the other hand, due to the precious nature of the
Windows CE screen real estate, Windows CE windows do not have any non-client areas. Windows CE applications will never
get any WM_NCxxx messages.
Stylus/Mouse Functions
Table 8.3 lists all the Win32 mouse-related functions and provides a description of their functionality as supported by
Windows CE.
Table 8.3
Stylus/Mouse Functions
Function
DragDetect
Description
Not supported for Windows CE.
Retrieves the handle of the window (if
GetCapture
any) that has captured the stylus.
Retrieves the current double-click time
GetDoubleClickTime
for the stylus.
mouse_event
Not supported for Windows CE.
Releases the stylus capture from a
ReleaseCapture
window in the current thread and
restores normal stylus input processing.
continues
Page 218
Table 8.3
Stylus/Mouse Functions, continued
Function
Description
Sets the stylus capture to the specified
window belonging to the current thread.
After a window has captured the stylus,
SetCapture
all stylus input is directed to that
window. Only one window at a time can
capture the stylus.
SetDoubleClickTime Not supported for Windows CE.
SwapMouseButton Not supported for Windows CE.
Cursor Functions
Table 8.4 lists all the Win32 cursor-related functions and provides a description of their functionality as supported by
Windows CE.
Table 8.4
Cursor Functions
Function
Description
ClipCursor
Not supported for Windows CE.
CopyCursor Not supported for Windows CE.
CreateCursor Not supported for Windows CE.
DestroyCursor Not supported for Windows CE.
GetClipCursor Not supported for Windows CE.
GetCursor
Not supported for Windows CE.
Not
supported
GetCursorPos
for
Windows
CE.
Not
supported
LoadCursor
for
Windows
CE.
Not
supported
LoadCursorFromFile for
Windows
CE.
Establishes
the cursor
shape. For
Windows
SetCursor
CE, it can
only turn
on or off
the wait
cursor.
Not
supported
SetCursorPos
for
Windows
CE.
Previous | Table of Contents | Next
Function
SetSystemCursor
ShowCursor
Description
Not supported for Windows CE.
Not supported for Windows CE.
Stylus/Mouse Messages
Table 8.5 lists Win32 mouse messages and a description of their Windows CE functionality.
Table 8.5
Stylus/Mouse Messages
Message
Description
Sent to the window that is losing
WM_CAPTURECHANGED
the mouse capture.
Sent when the user double-taps
the touch-screen while the cursor
is in the client area of a window.
If the stylus is not captured, the
WM_LBUTTONDBLCLK message is posted to the window
beneath the cursor. Otherwise,
the message is sent to the
window that has captured the
stylus.
Sent when the user presses the
touchscreen while the cursor is in
the client area of a window. If
the stylus is not captured, the
WM_LBUTTONDOWN
message is posted to the window
beneath the cursor. Otherwise,the
message is sent to the window
that has captured the stylus.
Sent when the user releases the
stylus from the touch-screen
while the cursor is in the client
area of a window. If the stylus is
WM_LBUTTONUP
not captured, the message is
posted to the window beneath the
cursor. Otherwise,the message is
sent to the window that has
captured the stylus.
continues
Page 220
Table 8.5
Description
Not supported for Windows
WM_MBUTTONDBLCLK
CE.
Not supported for Windows
WM_MBUTTONDOWN
CE.
Not supported for Windows
WM_MBUTTONUP
CE.
Not supported for Windows
WM_MOUSEACTIVATE
CE.
Posted to a window when the
stylus moves.If the stylus is
not captured, the message is
posted to the window that
WM_MOUSEMOVE
contains the cursor. Otherwise,
the message is posted to the
window that has captured the
mouse.
Not supported for Windows
WM_NCHITTEST
CE.
Not supported for Windows
WM_NCLBUTTONDBLCLK
CE.
Not supported for Windows
WM_NCLBUTTONDOWN
CE.
Not supported for Windows
WM_NCLBUTTONUP
CE.
Not supported for Windows
WM_NCMBUTTONDBLCLK
CE.
Not supported for Windows
WM_NCMBUTTONDOWN
CE.
Not supported for Windows
WM_NCMBUTTONUP
CE.
Not supported for Windows
WM_NCMOUSEMOVE
CE.
Not supported for Windows
WM_NCRBUTTONDBLCLK
CE.
Not supported for Windows
WM_NCRBUTTONDOWN
CE.
Not supported for Windows
WM_NCRBUTTONUP
CE.
Not supported for Windows
WM_RBUTTONDBLCLK
CE.
Not supported for Windows
WM_RBUTTONDOWN
CE.
Not supported for Windows
WM_RBUTTONUP
CE.
Page 221
TravelManager Stylus or Mouse Use
Although stylus input is fundamental to any Windows CE application, most of the functionality is handled automatically
by the operating system. Tapping on the menu bar, tapping on the drop-down box of a combo box, or double-tapping on
an item in a list are all handled by Windows CE, which then performs some action.
The Draw view of the TravelManager application is one area where the application processes basic stylus input. In order
to implement drawing onto the screen, the application catches the WM_LBUTTONDOWN, WM_LBUTTONUP, and
WM_MOUSEMOVE messages in the WndProc function and dispatches them to virtual methods of the Window class.
These WMLButtonDown, WMLButtonUp, and WMMouseMove methods of the DrawView class then perform the
drawing operations. The code for the aforementioned methods is shown in the display output section of this chapter.
Timer Input
Although not directly related to user interaction, one mechanism an application can use for input is timers. Like Win32,
the Windows CE timer is an input device that periodically notifies an application when a specified interval of time has
elapsed. Timers can obviously be used to display time, but timers can also be used to update information on the screen,
implement an autosave feature, or dismiss an initial "splash" screen.
Display Output
Previous chapters covered many methods for putting information on the screen. In the first "Hello Windows CE"
application, a window was created on the screen and displayed the text Hello Windows CE in the center of the window.
The TravelManager application uses windows, dialog boxes, and other controls to present information on the screen.
Whether an application writes text to the screen or asks Windows CE to display entire dialog boxes, the actual displaying
of graphics on the video display is the job of the Graphics Device Interface (GDI) subsystem. The GDI subsystem
provides a low-level, but common, interface to the display hardware. In Windows CE, the GDI functionality is actually
part of the Graphics, Windowing, and Events Subsystem (GWES).
Previous | Table of Contents | Next
The Win32 GDI subsystem supports a variety of graphics functions, which can be divided into the following categories:
Lines and curves
Filled areas
Bitmaps
Text
Mapping modes and transforms
Metafiles
Regions
Paths
Clipping
Palettes
Printing
The Windows CE GDI subsystem supports a subset of the Win32 GDI functions. Given the large number of GDI related
functions, this section concentrates mainly on the differences between Windows CE and Win32.
Many GDI functions from Win32 do not make sense for the small footprint of Windows CE-based devices, or they place
too much of a burden on the limited system resources. As a result, Windows CE has excluded many Win32 GDI functions.
The following list describes some of the functions or categories of the GDI subsystem that currently are not supported in
Windows CE:
Printing and the device contexts. These are used to store attributes that govern how the GDI operates on printers.
TrueType fonts. Windows CE supports only raster fonts. There are seven rasterized system fonts available in several
sizes that are stored in ROM.
Page 225
Color and custom palettes. Colors are mapped to two-bit-per-pixel grayscale. The Visual C++ IDE provides a
resource editor for creating bitmaps and icons with the grayscale palette.
Coordinate space transformation functions. Examples include SetMapMode, GetMapMode, SetViewportExt, and
SetWindowExt.
bit block transfers. The system provides only limited support for bit block transfers (BitBlt).
current point. The concept of a current point is not supported, so most line drawing functions are not available.
(PolyLine is used instead.)
Cursors. Except for the wait cursor (the spinning hourglass), cursors are not supported. Applications cannot show
active targets by changing the size or shape of the cursor.
Arc or Pie. Neither Arc nor Pie is supported in Windows CE. To create an arc, use Ellipse with an appropriately
defined clipping region.
GetStockObject. Cannot be used with DEFAULT_PALETTE or any font other than SYSTEM_FONT.
In most application functionality using GDI functions, knowing the screen or display size is very important. The standard
screen size for the initial generation of Handheld PCs is 480240 pixels. However, future Handheld PCs have already been
announced that will utilize larger screen resolutions.
Tip
Applications should use the GetSystemMetrics function call (with SM_CXSCREEN and SM_CYSCREEN) to
get the full screen size. Also be sure to subtract the height of any command bar in order to get the usable
screen size.
Page 226
Due to the limited functionality, the Windows CE SDK documentation suggests writing bitmaps to Windows CE using
DIBSections. In order to do this, the following sequence of steps may be useful:
1. Determine the size of the source bitmap (HBITMAP) using GetObject.
2. Create a DIBSection of that size and appropriate bit depth.
3. Select both the source and the DIBSection into memory DCs and Blt source to DIBSection.
4. Open the file and write the BITMAPFILEHEADER.
5. Write the BITMAPINFO.
6. Write the bits.
7. Close the file, delete the DIBSection, and so on.
A DIBsection can't be used like a palette device to simply change the color table to get a different image. Color 0 is black,
color 1 is dark gray, color 2 is light gray, and color 3 is white. Creating a color table that tries to map otherwise will fail. In
order to change a portion of an image from dark gray to light gray, all the relevant bits must be changed from 1 to 2.
Painting and Drawing Functions
Table 8.7 lists most of the GDI-related functions and provides a description of their functionality as supported by Windows
CE.
Table 8.7
GDI Functions
Function
Description
Prepares the specified window for painting and fills
BeginPaint a PAINTSTRUCT structure with information about
the painting.
Page 227
Function
Description
Performs a bit-block transfer of the color
data corresponding to a rectangle of
pixels from the specified source device
context into a destination device context.
BitBlt
(The only supported raster operations are
SRCCOPY, SRCAND, SRC PAINT, and
SRCINVERT. Mirroring is not
supported.)
DrawAnimatedRects Not supported for Windows CE.
DrawCaption
Not supported for Windows CE.
DrawEdge
Draws one or more edges of a rectangle.
Draws a rectangle in the style used to
DrawFocusRect
indicate that the rectangle has the focus.
DrawFrameControl Not supported for Windows CE.
DrawState
DrawStateProc
DrawTextEx
Description
Retrieves a handle of a display device
context (DC) for the client area of the
specified window. The display device
GetDC
context can be used in subsequent GDI
functions to draw in the client area of the
window.
Retrieves device-specific information about
GetDeviceCaps
a specified device.
Retrieves the red, green, blue (RGB) color
GetPixel
value of the pixel at the specified
coordinates.
GetROP2
Not supported for Windows CE.
Retrieves a handle to one of the predefined
stock pens, brushes, or fonts. Windows CE
does not support the following stock
GetStockRObject objects: ANSI_FIXED_FONT,
ANSI_VAR_FONT, OEM_FIXED_FONT,
SYSTEM_FIXED_FONT,
DEFAULT_PALETTE.
Retrieves the dimensions (widths and
heights) of Windows display elements and
GetSystemMetrics system con figuration settings. All
dimensions retrieved by GetSystemMetrics
are in pixels.
Retrieves the coordinates of the smallest
rectangle that completely encloses the
update region of the specified window in
GetUpdateRect
client coordinates. If there is no update
region, GetUpdateRect retrieves an empty
rectangle and sets all coordinates to zero.
Retrieves the update region of a window by
copying it into the specified region. The
GetUpdateRgn
coordinates of the update region are relative
to the upper-left corner of the window (that
is, they are client coordinates).
GetWindowDC
Keyword
Brief
Full
Advanced
Search
Search Tips
Function
GrayString
Description
Not supported for Windows CE.
Adds a rectangle to the specified
window's update region. The update
InvalidateRect
region represents the portion of the
window's client area that must be
redrawn.
InvalidateRgn
Not supported for Windows CE.
LineTo
Not supported for Windows CE.
LockWindowUpdate Not supported for Windows CE.
Combines the color data for the source
and destination bitmaps using the
specified mask and raster operation.
MaskBlt
Note: Windows CE sup- ports only raster
operations of SRCCOPY and
SRCINVERT.
MoveTo
Not supported for Windows CE.
OutputProc
Not supported for Windows CE.
Paints the given rectangle using the brush
that is currently selected into the
PatBlt
specified device context. The brush color
and the surface color(s) are combined by
using the given raster operation.
Draws a polygon consisting of two or
more vertices connected by straight lines.
The poly- gon is outlined by using the
Polygon
current pen and filled by using the current
brush and the poly- gon fill mode.
However, note: only convex polygons are
supported in Windows CE.
Draws a series of line segments by
Polyline
connecting the points in the specified
array.
PaintDesktop
Not supported for Windows CE.
RedrawWindow
Not supported for Windows CE.
Releases a device context (DC), which
frees it for use by other applications. The
ReleaseDC
effect of the ReleaseDC function depends
on the type of device context.
Page 230
Table 8.7
GDI Functions, continued
Function
ResetDisplay
Description
Not supported for Windows CE.
Sets the current background color to the
speci- fied color value, or to the nearest
SetBkColor
physical col- or if the device cannot
represent the specified color value.
Sets the background mix mode of the
specified device context. The background
SetBkMode
mix mode is used with text, hatched brushes,
and pen styles that are not solid lines.
SetBoundsRect Not supported for Windows CE.
Sets the pixel at the specified coordinates to
SetPixel
the specified color.
SetRectRgn
Not supported for Windows CE.
SetROP2
Not supported for Windows CE.
Copies a bitmap from a source rectangle into
a destination rectangle, stretching or
compress- ing the bitmap to fit the
dimensions of the destination rectangle, if
StretchBlt
necessary. Windows stretches or compresses
the bitmap according to the stretching mode
currently set in the destination device
context.
Updates the client area of the specified window by sending a WM_PAINT message to
the window if the window's update region is
not empty. The function sends a
UpdateWindow
WM_PAINT message directly to the window
procedure of the specified window,
bypassing the application queue. If the
update region is empty, no mes- sage is sent.
Validates the client area within a rectangle
ValidateRect
by removing the rectangle from the update
region of the specified window.
ValidateRgn
Not supported for Windows CE.
WindowFromDC Not supported for Windows CE.
Page 231
Table 8.8 lists the Win32 GDI messages and a description of their Windows CE functionality.
Table 8.8
GDI Messages
Message
Description
WM_DISPLAYCHANGE Not supported for Windows CE.
Sent to prepare an invalidated
WM_ERASEBKGND
portion of a window for painting.
WM_ICONERASEBKGND Not supported for Windows CE.
WM_NCPAINT
Not supported for Windows CE.
Sent to inform an application that
part or all of the window's client
WM_PAINT
area is invalid and must be
repainted.
WM_PAINTICON
Not supported for Windows CE.
WM_PRINT
WM_PRINTCLIENT
WM_SETREDRAW
The WMLButtonDown, WMLButtonUp, and WMMouseMove methods track whether the stylus is up or down,
give the points of the stylus, and then draw the line between the specific points.
LRESULT DrawView::WMLButtonDown(HWND, UINT, WPARAM, LPARAM lParam)
{
bLBDown = TRUE;
line[0].x = LOWORD(lParam);
line[0].y = HIWORD(lParam);
return 0;
}
LRESULT DrawView::WMLButtonUp(HWND, UINT, WPARAM, LPARAM)
{
bLBDown = FALSE;
return 0;
}
LRESULT DrawView::WMMouseMove(HWND, UINT, WPARAM, LPARAM lParam)
{
if ( bLBDown == TRUE )
{
HDC hdc = GetDC(m_hWnd);
line[1].x = LOWORD(lParam);
line[1].y = HIWORD(lParam);
if((line[0].x != line[1].x) || (line[0].y != line[1].y))
{
HPEN oldPen = (HPEN)SelectObject(hdc, m_hPen);
Polyline(hdc, line, 2);
SelectObject(hdc, oldPen);
//reset value of initial point to end point
line[0] = line[1];
}
ReleaseDC(m_hWnd, hdc);
}
return 0;
}
Previous | Table of Contents | Next
Description
Not supported for Windows CE.
Closes the clipboard.
Page 235
Function
CountClipboardFormats
EmptyClipboard
EnumClipboardFormats
GetClipboardData
Description
Retrieves the number of different
data formats currently on the
clipboard.
Empties the clipboard and frees
handles to data in the clipboard.
Enumerates the data formats that
are currently available on the
clipboard.
Retrieves data from the clipboard
in a specified format.
CloseClipboard();
}
}
Sound Output
A small but powerful feature of Windows CE is the capability for an application to easily play a sound. Applications can
use a sound to get
Page 237
theuser's attention, provide feedback on the progress of an operation, or play backa recorded dictation.
Sound Output in Windows CE
The entire functionality for sound output in Windows CE is accomplished through one API function, sndPlaySound. The
parameters to sndPlaySound are LPCSTR lpszSound and UINT fuSound, which are described as follows:
LPCSTR lpszSound. String that specifies the sound to play.
The lpszSound parameter specifies the sound to play. This parameter can be an entry in the registry, a pointer to an
image of a .wav file that identifies a system sound, or the name of a waveform-audio file. If the function does not find
the entry, the parameter is treated as a file name. If this parameter is NULL, any currently playing sound is stopped.
The fuSound parameter specifies a flag for playing the sound. The available flags are listed in Table 8.10.
Table 8.10
Sound Output Flags
Value
Meaning
The sound is played asynchronously and the
function returns immediately after beginning
SND_ASYNC the sound. To terminate an asynchronously
played sound, call sndPlaySound with
lpszSound set to NULL.
The sound plays repeatedly until
sndPlaySound is called again with the
SND_LOOP
lpszSound parameter set to NULL. You must
also specify the SND_ASYNC flag to loop
sounds.
The parameter specified by lpszSound points
SND_MEMORY to an image of a waveform sound in
memory.
continues
Page 238
Table 8.10
Sound Output Flags, continued
Value
Meaning
If a sound cannot be found, the function
SND_NODEFAULT returns silently without playing the
default sound.
If a sound is currently playing, the
SND_NOSTOP
function immediately returns FALSE,
without playing the requested sound.
The sound is played synchronously and
SND_SYNC
the function does not return until the
sound ends.
Interprets lpszSound only as an event
SND_ALIAS
name to be found in the registry.
Interprets lpszSound only as a file name
SND_FILENAME to be loaded from the filesystem (.wav
extension optional).
Notifications
As you've seen so far, most of the input and output methods available in
Windows CE are slimmed-down versions of features available in Win32.
However, notification support is a feature that is only available with Windows
CE. This special set of functions enables Windows CE to notify the user or an
application of various events, whether the device is on or off. Windows CE,
for example, might play a sound or flash the LED light in a schedule
application just prior to a scheduled meeting.
Notification Types
Windows CE can generate two main types of notifications: user notifications
and application notifications.
User notifications are designed to alert the user about an event at a specific
time. The user may be alerted by the appearance of an icon in the notification
area of the taskbar, a sound, the display of a message, the flashing of the LED
light, or the vibrating of the device. The user is usually required to
acknowledge the notification in some way-for instance, clicking the OK button
in the dialog box that notifies the user of an appointment.
The application has control of which notification options to use; however, the
user should be able to choose notification preferences. Applications can
display the system-provided notification options dialog box, which enables the
user to choose the preferred notification option. This mechanism also enables
the application to recognize which notification options the host device
supports. Not all Handheld PCs, for example, may support a notification LED
light, and none currently support the notification option of vibrating the
device.
Application notifications are designed to alert applications about some system
event or that a specific time has been reached. When the given system event or
time has been reached, Windows CE automatically starts the application that
requested notification of the event or time. When the application starts as the
result of a notification, a command-line parameter identifies the event that
occurred.
Page 240
The main difference between a user notification and an application notification
is that a user notification is handled entirely by the Windows CE operating
system (such as displaying a dialog box, playing a sound, and so on). For an
application notification, Windows CE starts the requested application but does
no other processing of the notification. In addition, a user notification alerts the
user of some event, whereas an application notification alerts an application
(which in turn may alert the user).
Programming Windows CE Notifications
Windows CE uses notifications to communicate with the user and Windows
CE-based applications. A notification is a signal from the operating system
that an event has occurred. This could be a timer event or a system event such
as establishing a network connection. An application registers a notification
for an event and the system generates a notification when the event occurs.
Windows CE provides an application programming interface (API) that can be
used to register events and select options that determine the type of
notification. The following sections describe the notification API.
Setting User Notifications
All user notifications include a taskbar annunciator. The user can also be
notified of an event in one of the following ways (although not all devices
support all options):
Displaying a dialog box.
Page 242
An application should determine user notification preferences prior to setting a
user notification. An application uses the PegGetUser NotificationPreferences
function to get the user's preferences for a particular notification. The
parameters to PegGetUserNotification Preferences are as follows:
HWND. Parent window for dialog box.
The taskbar annunciator for an active notification remains in the taskbar until
the user handles the notification. The user can tap the annunciator icon to start
the application. Starting the application removes the taskbar annunciator. The
application then calls the PegHandleAppNotifications function to remove the
taskbar annunciator.
Note
If a notification includes a dialog box, tapping the OK button
automatically handles the notification.
An application can mark all its active notifications as handled by calling the
PegHandleAppNotifications function. The function handles notifications only
for the given application.
An application can also remove a notification before it becomes active. A user
may set an alarm, for example, but then delete the alarm before it has gone off.
An application uses the PegClearUserNotification function to delete a
registered notification. The only parameter to the
Previous | Table of Contents | Next
Notification Functions
The functions listed in Table 8.11 are used to create and manage Windows CE
notifications.
Page 245
Table 8.11
Notification Functions
Function
PegClearUserNotification
PegGetUserNotification
Preferences
PegHandleAppNotifications
PegRunAppAtEvent
PegRunAppAtTime
PegSetUserNotification
Description
Deletes a user notification
that was created by a
previous call to the function
PegSetUserNotification.
This function does not
operate on notifications that
have already gone off (see
PegHandle
AppNotifications).
Queries the user for
notification settings by
displaying a dialog box
showing options that are
valid for the current
hardware plat form.
Marks as "handled," all
notifications previously
registered by the given
applications that have gone
off. The function turns off
the sound and LED, stops
vibration, and removes the
taskbar annunciator.
Starts running an application
when the given event occurs.
Requests the system to start
running the given
application at the given time.
Creates a new user
notification or modifies an
existing one.
Notification Structures
The PegSetUserNotification and PegGetUserNotificationPreferences functions
both use the PEG_USER_NOTIFICATION structure. This structure is passed
in the PegGetUserNotificationPreferences function. It contains information
used to initialize the user notifica-tions settings dialog box, and receives the
user's notification preference entered by way of the dialog box. These user
preferences should be saved and considered when setting notifications. The
PEG_USER_NOTIFICATION structure is also used when calling
PegSetUserNotification to describe what should happen when the notifi- cation
time is reached.
Page 246
The structure is defined in the following code:
Meaning
Flashes the LED. The LED continues to flash
PUN_LED
until the notification is handled.
Vibrates the device. No Handheld PCs
PUN_VIBRATE
currently support this option.
Displays the user notification dialog box.
When this structure is passed to the
PegSetUserNotification function, the
pwszDialogTitle and pwszDialogText
PUN_DIALOG members must provide the title and text of
the dialog box. The notification dialog box
contains an OK button and a snooze button.
The snooze button causes the dialog box to
be redisplayed in 5 minutes.
Plays the sound specified by the pwszSound
member. When passed to PSVN, the
PUN_SOUND
pwszSound member must provide the name
of the sound file.
Repeats the pwszSound for 10-15 seconds.
PUN_REPEAT
Only valid if PUN_SOUND is set.
Page 247
pwszDialogTitle. Specifies the title of the user notification dialog box. If
this parameter is NULL, no dialog box is displayed. The
PegGetUserNotificationPreferences function ignores this member.
Keyword
Brief
Full
Advanced
Search
Search Tips
The notification is set in the AboutDlg::WMInitDialog method. It sets the notification method to flash
the LED light and sets the notification time to 2 seconds after the current time.
void AboutDlg::WMInitDialog(HWND hDlg)
{
PEG_USER_NOTIFICATION notificationSettings;
SYSTEMTIME time;
notificationSettings.ActionFlags = PUN_LED;
notificationSettings.dwReserved = 0;
GetLocalTime(&time);
time.wSecond+=2;
m_notification = PegSetUserNotification( 0, L"trvlmgr.exe", &time,
¬ificationSettings);
if (m_notification != 0)
{
SetTimer(hDlg, 1, 15000, NULL);
}
}
The notification is handled in either the AboutDlg::WMCommand method or the AboutDlg::WMTimer
method, depending on whether the dialog box is being closed by the user or by the timer going off. (The
AboutDlg::WMTimer method was discussed in the "Timers," section of this chapter.)
LRESULT AboutDlg::WMCommand( HWND hDlg, UINT, WPARAM wParam, LPARAM )
{
if ((wParam == IDOK) || (wParam == IDCANCEL))
{
PegHandleAppNotifications(L"trvlmgr.exe");
KillTimer(hDlg, 1);
EndDialog(hDlg, TRUE);
return (TRUE);
}
return FALSE;
}
Page 249
CHAPTER 9
Note
Remember that when the Handheld PC is turned off, power still
is being used to maintain the state of the operating system. This
includes maintaining the object store and the state of the current
running
applications.
The Windows CE registry and file system will be covered in this chapter. The
Windows CE database system will be covered in Chapter 10, "Windows CE
Databases."
In Figure 9.1, the entries in the left pane are the keys and subkeys; the entries
in the right pane are the values for the HKEY_CURRENT_
USER\Software\Microsoft\Excel\Pocket 1.0\Microsoft Excel key. This key has
no default value, but it does have three other numeric values.
Predefined Keys
An application must open a key before it can add data to the registry. To open
a key, an application must supply the handle of another key in the registry that
is already open. The system defines standard handles that are always open. An
application can use these predefined handles as entry points to the registry.
Page 254
Windows CE contains only a subset of the predefined keys that are present in
Windows 95. Table 9.1 defines the root keys.
Table 9.1
Windows CE Registry Keys
Registry Key
Description
This key defines document types
and the properties associated
HKEY_CLASSES_ROOT with those types, such as an icon
to display and how to open that
type document.
This key defines settings for the
HKEY_CURRENT_USER
current user.
This key defines settings for the
HKEY_LOCAL_MACHINE
machine.
This key defines the settings and
HKEY_USERS
preferences for each user.
Value Types
The registry supports several different data types that an application can use
when inserting values into the registry. Table 9.2 lists the supported types.
Table 9.2
Windows CE Registry Data Types
Data Type
REG_BINARY
REG_DWORD
Description
Binary data in any form.
A 32-bit number.
A 32-bit number in
REG_DWORD
little-endian format
(same as REG_DWORD). In
little-endian format, the most
_LITTLE_ENDIAN
significant byte of a word is
the high-order word.
A 32-bit number in
big-endian format. In
REG_DWORD_BIG _ENDIAN big-endian format, the most
significant byte of a word is
the low-order word.
Page 255
Data Type
Description
A null-terminated string that
contains unexpanded references to
environment variables (for example,
REG_EXPAND_SZ
"%PATH%"). This string will be a
Unicode or ANSI string, depending
on whether you use the Unicode or
ANSI functions.
REG_LINK
A Unicode symbolic link.
An array of null-terminated strings,
REG_MULTI_SZ
terminated by two null characters.
REG_NONE
No defined value type.
REG_RESOURCE_LIST A device-driver resource list.
REG_SZ
A null-terminated Unicode string.
Registry Tools
Windows 95 contains a tool called the Registry Editor that enables direct
interaction with the registry. Although not usually needed by end users, this
tool permits advanced users fast and easy access to the settings in the registry.
In contrast, Windows CE does not contain a direct registry editing tool.
The Windows CE SDK does provide a Remote Registry Editor that can be
used to examine and even update the Windows CE registry from a desktop PC.
This tool is especially useful for verifying the results of registry programming
when developing an application.
Although the end user does not have direct interaction with the registry,
applications can interact with the registry in a variety of ways. When an
application is installed, the setup mechanism can update the registry, or a
desktop application connected to a Windows CE device can update the registry
through the remote registry API functions. A Windows CE application's
primary function, however, is to interact with the registry using the registry
functions in the Windows CE API.
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
Registry Uses
An application can use the registry in many ways. Most applications use the registry for saving application settings
and preferences. Applications can also manipulate settings and preferences for Windows CE itself through entries in
the registry.
Registering Filename Extensions
Windows CE supports the notion of file extension identifiers. This enables Windows CE to identify the type
associated with a given file extension. The registry information for these file extensions is found under the
HKEY_CLASSES_ROOT key. In order for an application to define its file extension, it should accomplish the
following duties:
1. Make sure that the file extension does not conflict with one that is already defined in the registry.
2. Enter a new key namethe key name should match the file extension name. (The default value of the key
should be an application identifier.) For example, to register files with the extension .abc and an application
identifier of abcfile, the key would be as follows:
HKEY_CLASSES_ROOT
.abc = abcfile
3. Next, add another key to HKEY_CLASSES_ROOT with the same name as the application identifier just
created. (The default value is a text string that describes the file type.)
HKEY_CLASSES_ROOT
abcfile = "ABC Application Document"
Generally, an application adds its document type to the registry during installation. The procedure used to install an
application onto a Windows CE Handheld PC facilitates adding this information to the registry. The installation
procedure itself will be covered in Chapter 12, "Windows CE Application Loader."
Page 257
Registering an Icon
In addition to creating a string that describes the file type, an application also can set the icon that is displayed for its
file extension. To specify the icon, another key is added under the application identifier key, which was created
earlier.
HKEY_CLASSES_ROOT
abcfile = "ABC Application Document"
DefaultIcon = \Windows\abcview.exe, 1
The value for the DefaultIcon key consists of a path to a resource (usually an .exe or .dll) and an offset where the
icon is located. The icon setting in the registry also can be created when an application is installed. This installation
Besides setting information about its document types, an application can use the registry to store a variety of
information. An application interacts with the registry using Windows CE API functions. Windows CE supports
most of the registry API functions that are available in Win32. The supported functions are described in the
following sections.
Applications can place data anywhere in the registry hierarchy. However, applications should create a key (with the
application's name) under the HKEY_LOCAL_MACHINE\SOFTWARE and
HKEY_CURRENT_USER\SOFTWARE keys.
Opening and Creating Keys
Before an application can add data to the registry, it must create or open a key. To create or open a key, an
application refers to the key as a subkey of another currently open key. The four predefined keys are always open;
an application does not need to open each subkey individually when opening a key with the other keys above it.
However, the application must start from an open key.
Page 258
An application uses the RegOpenKeyEx to open a key:
LONG RegOpenKeyEx(
HKEY hKey,
LPCWSTR lpszSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
//
//
//
//
//
);
The RegCreateKeyEx function creates the specified key. The system then creates the necessary structure to add the
key, including producing any intermediate keys not yet present in the registry. If the key already exists in the
registry, the function opens it. The RegCreateKeyEx function is defined as follows:
LONG RegCreateKeyEx(
HKEY hKey,
// handle of an open key
LPCWSTR lpszSubKey,
// address of subkey name
DWORD Reserved,
// reserved, must be zero
LPWSTR lpszClass,
// address of class string
DWORD dwOptions,
// not used, should be zero
REGSAM samDesired,
// not used, should be zero
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // not used
PHKEY phkResult,
// address of buffer for opened key
LPDWORD lpdwDisposition
// address of disposition value buffer
);
Tip
In Windows CE, the dwOptions and samDesired parameters are ignored and should be set to zero to
ensure compatibility with future versions of Windows CE. The lpSecurityAttributes parameter should
be set to NULL. Windows CE automatically assigns the key a default security descriptor.
Page 259
Closing Keys
An application uses the RegCloseKey function to close a key and write the data it contains to the object store. In
Windows CE, the data automatically is written to the registry before the RegCloseKey function returns. Other
versions of Win32 define a RegFlushKey function, but this is unnecessary in Windows CE.
LONG RegCloseKey(
HKEY hKey
);
);
Page 260
LONG RegDeleteKey(
HKEY hKey,
LPCWSTR lpszSubKey
);
DWORD dwIndex,
// index of value to query
LPWSTR lpszValueName, // address of buffer for value string
LPDWORD lpcchValueName,
// address for size of value
Keyword
Brief
Full
Advanced
Search
Search Tips
buffer
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
// reserved
// address of buffer for type code
// address of buffer for value data
// address for size of data buffer
);
Retrieving Registry Data
To retrieve information about a particular key, an application uses the RegQueryInfoKey function. To retrieve a
particular value for a key, an application uses the RegQueryValueEx function. The RegQueryInfoKey and
RegQueryValueEx are defined as follows:
LONG RegQueryInfoKey (
HKEY hKey,
// handle of key to query
LPWSTR lpszClass,
// address of buffer for class string
LPDWORD lpcchClass,
// address of size of class string buffer
LPDWORD lpReserved,
// reserved, must be NULL
LPDWORD lpcSubKeys,
// address of buffer for
number of subkeys
LPDWORD lpcchMaxSubKeyLen,
// address of buffer for
longest subkey name length
LPDWORD lpcchMaxClassLen,
// address of buffer for
longest class string length
LPDWORD lpcValues,
// address of buffer for
number of value entries
LPDWORD lpcchMaxValueNameLen, // address of buffer for
longest value name length
LPDWORD lpcbMaxValueData,
// address of buffer for
longest value data length
LPDWORD lpcbSecurityDescriptor,
// not used, must be NULL
PFILETIME lpftLastWriteTime
// not used, must be NULL
);
LONG RegQueryValueEx(
Page 262
HKEY hKey,
// handle of key to query
LPCWSTR lpszValueName,
// address of name of value to query
LPDWORD lpReserved,
// reserved, must be NULL
LPDWORD lpType,
// address of buffer for value type
LPBYTE lpData,
// address of data buffer
LPDWORD lpcbData
// address of data buffer size
);
Memory and the Registry
On any platform, limiting memory use is important. Windows CE's memory restraints, however, make effective
memory use even more critical. To decrease access times and reduce memory requirements, the sizes of registry entries
can be limited according to the following guidelines:
Limit the length of each key name component.
Do not use the null (default) value name; this wastes the key above the value.
Do not use many small registry values; use larger values (such as multistrings or binary) rather than many
individual strings or integers.
Do not use the Windows 95 key-naming convention just for the sake of doing so.
Keep the registry values to a reasonable size; do not add multi-kilobyte values.
Note
Because the registry is not exposed to the end user, registry keys do not need to follow a traditional
naming convention.
Page 263
TravelManager Registry Use
Most applications have many potential registry uses for the system registry. For the TravelManager application, one
such use is to save the current view when the user closes the application. This is done so that when the application is
restarted, the user sees the same view before he previously closed the application.
The current view is saved to the registry in the SaveCurrentState method of the MainWindow class. This method opens
or creates the SOFTWARE\WINDOWS CE PROGRAMMING\TRAVELMANAGER registry key using the
RegCreateKeyEx function. The process then determines the currently visible view and saves that information to the
registry using the RegSetValueEx function. The registry is then closed using the RegCloseKey function.
TravelManager's SaveCurrentState function is listed as follows:
void MainWindow::SaveCurrentState()
{
HKEY hKey;
DWORD dwDisp, dwState;
HRESULT hRes;
hRes = RegCreateKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Windows CE
Programming\\TravelManager", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisp);
if (hRes != ERROR_SUCCESS)
{
MessageBox(NULL, L"CreateKey failed", L"", MB_OK);
return;
}
dwState = 0;
if (IsWindowVisible(m_pItineraryView->m_hWnd))
dwState = 1;
else if (IsWindowVisible(m_pExpensesView->m_hWnd))
dwState = 2;
else if (IsWindowVisible(m_pNotesView->m_hWnd))
dwState = 3;
else if (IsWindowVisible(m_pDrawView->m_hWnd))
dwState = 4;
Page 264
Page 265
Page 266
case 0:
default:
CheckMenuItem(hMenu, ID_VIEW_ITINERARY, MF_CHECKED);
SendMessage(m_hwndCB, TB_SETSTATE, (WPARAM)ID_VIEW_ITINERARY,
MAKELONG(TBSTATE_ENABLED|TBSTATE_CHECKED,0));
ShowWindow(m_pItineraryView->m_hWnd, SW_SHOW);
break;
}
}
needed off this root directory. The \Windows directory is important because all ROM files actually appear in this
directory. Most files in the \Windows directory are in ROM, but the user or an application also can place files in the
\Windows directory. If a file is placed in the \Windows directory that has the same name as a file in ROM, the file in
RAM takes precedence. Windows CE does support long file names, which makes it easier to produce unique file names
and avoid the possibility of a naming collision.
The Windows CE file system has certain constraints. First, this file system has no concept of a current directory. File
specification always must be explicit, not relative to a current directory. Second, no PATH
Previous | Table of Contents | Next
environment variable exists, so Windows CE cannot scan a PATH list to search for a file. The exception to this rule is that
Windows CE always looks in the \Windows directory when trying to locate a DLL. For this reason, all EXE and DLL files
should be placed in the \Windows directory. Links then can be placed on the desktop or in the My Programs folder.
Because memory is so limited under Windows CE, the entire file system is always compressed at a ratio of about 2:1 to
conserve RAM. There is no way to turn off the compression, but you should have no need to do so because this
compression is completely transparent. Furthermore, the object store does not use the FAT structure, so no cluster size
issues arise and no space is wasted when storing a file. With memory at such a premium, the file system is optimized for
size, not speed. The system does, however, do some minimal caching to improve performance.
Working with Directories
Directories exist in Windows CE just as they do in Windows 95. Applications can create directories with the
CreateDirectory function and delete directories with the RemoveDirectory function. The CreateDirectory function is
defined as follows:
BOOL CreateDirectory(
LPCTSTR lpPathName,
// pointer to a
directory path string
LPSECURITY_ATTRIBUTES lpSecurityAttributes
// should be NULL
);
In Windows CE, the lpSecurityAttributes parameter is ignored and should be set to NULL. The RemoveDirectory function
is defined as follows:
BOOL RemoveDirectory(
LPCTSTR lpPathName
);
Page 268
Creating and Opening Files
An application uses the CreateFile function to create, open, or truncate a file, pipe, or communications resource. The
application then returns a handle that can be used to access the object. The CreateFile function is defined as follows:
HANDLE CreateFile(
LPCTSTR lpFileName,
// pointer to name of the file
DWORD dwDesiredAccess,
// access (read/write) mode
DWORD dwShareMode,
// share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // ignored
DWORD dwCreationDistribution, // how to create
DWORD dwFlagsAndAttributes,
// file attributes
HANDLE hTemplateFile
// ignored
);
The differences between the Windows CE version of CreateFile and the regular Win32 version are detailed in the following
list:
In Windows CE, the lpSecurityAttributes parameter is ignored and should be set to NULL.
The following attribute flags are not supported in Windows CE for the dwFlagsAndAttributes parameter:
FILE_ATTRIBUTE_OFFLINE
FILE_ATTRIBUTE_TEMPORARY
The following file flags are not supported in Windows CE for the dwFlagsAndAttributes parameter:
FILE_FLAG_OVERLAPPED (However, multiple reads/ writes pending on a device at a time are allowed.)
FILE_FLAG_SEQUENTIAL_SCAN
FILE_FLAG_NO_BUFFERING
Page 269
FILE_FLAG_DELETE_ON_CLOSE
FILE_FLAG_BACKUP_SEMANTICS
FILE_FLAG_POSIX_SEMANTICS
The dwFlagsAndAttributes parameter does not support the SECURITY_SQOS_PRESENT flag in Windows CE or
its corresponding values.
The hTemplateFile parameter is ignored in Windows CE. As a result, CreateFile does not copy the extended
attributes to the new file.
);
Reading and Writing Data
After a file is opened, an application can read data from it with the ReadFile function. The ReadFile function reads data
from the file, starting at the position indicated by the file pointer. After the read operation has been completed, the file
pointer is adjusted by the number of bytes actually read.
Page 270
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
The differences between the Windows CE version of ReadFile and the regular Win32 version are detailed in the following
list:
The lpOverlapped parameter must be set to NULL. Windows CE does not allow files to be created with the
overlapped attribute.
Applications use the WriteFile function to write data to a file. The WriteFile function starts writing data to the file at the
position indicated by the file pointer. After the write operation has been completed, the file pointer is adjusted by the
number of bytes actually written.
BOOL WriteFile(
HANDLE hFile,
// handle of file to write to
LPCVOID lpBuffer,
// address of data to write to file
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten,
// address for # of bytes written
LPOVERLAPPED lpOverlapped
// must be set to NULL
);
Windows CE does not support asynchronous write operations. The lpOverlapped parameter is ignored and should be set to
NULL before calling this function.
Page 271
The WriteFile function typically writes data to an internal buffer that the operating system writes to disk on a regular basis.
The FlushFileBuffers function writes all the buffered information for the specified file to memory and is defined as follows:
BOOL FlushFileBuffers(
HANDLE hFile
// open handle to file
);
Copying and Moving Files
Applications also can copy or move an existing file. The file to be moved or copied does not need to be opened. Instead, the
CopyFile function is used to copy an existing file or a new file, and the MoveFile function is used to rename an existing file
or directory.
BOOL CopyFile(
LPCTSTR lpExistingFileName,
// pointer to name of an
existing file
LPCTSTR lpNewFileName, // pointer to name of file to copy to
BOOL bFailIfExists
// flag for operation if file exists
);
BOOL MoveFile(
LPCTSTR lpExistingFileName,
// address of name of the existing file
LPCTSTR lpNewFileNam // address of new name for the file
);
Finding Files
An application can use the FindFirstFile function to search a directory for the first file whose name matches the specified
search file name (this can include wild cards). FindFirstFile examines subdirectory names as well as file names. The
application subsequently can call the FindNextFile function repeatedly to retrieve all files and directories that match the
search file name. The FindClose function is used to
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
close the search handle returned from FindFirstFile when the search is complete. These three functions are defined as follows:
HANDLE FindFirstFile(
LPCTSTR lpFileName,
// pointer to name of file to search for
LPWIN32_FIND_DATA lpFindFileData
// pointer to returned information
);
BOOL FindNextFile(
HANDLE hFindFile,
// handle to search
LPWIN32_FIND_DATA lpFindFileData
// pointer to structure for data on found
);
BOOL FindClose(
HANDLE hFindFile
);
LPCTSTR lpFileName
);
GetFileInformationByHandle retrieves information about an open file.
BOOL GetFileInformationByHandle(
HANDLE hFile, // handle of file
Page 273
LPBY_HANDLE_FILE_INFORMATION lpFileInformation
address of structure
);
//
GetFileTime retrieves the date and time that a file was created, last accessed, and last modified.
BOOL GetFileTime(
HANDLE hFile,
LPFILETIME lpCreationTime,
LPFILETIME lpLastAccessTime,
LPFILETIME lpLastWriteTime
);
SetFileTime sets the date and time that a file was created, last accessed, or last modified.
Page 274
BOOL SetFileTime(
HANDLE hFile,
const FILETIME
const FILETIME
const FILETIME
);
SetEndOfFile moves the end-of-file position for the specified file to the current position of the file pointer.
BOOL SetEndOfFile(
HANDLE hFile
);
application then writes the data into the file with the WriteFile function. Finally, the file is closed with the CloseHandle
function.
Note that the code responsible for saving data to the File System is not compiled for an emulation build. The file system calls
are available under emulation, but are mapped directly to the Win32 file system calls. This means paths to a file would also
require a drive letter.
void NotesView::Save()
{
#ifndef _WIN32_WCE_EMULATION
DWORD length = SendDlgItemMessage(m_hWnd, IDC_EDIT1, WM_GETTEXTLENGTH, 0, 0);
TCHAR *pString = (TCHAR *) LocalAlloc( LPTR , (length * sizeof(TCHAR) + sizeof(
if (GetDlgItemText(m_hWnd, IDC_EDIT1, pString, length+1) == 0)
{
LocalFree(pString);
return; //nothing to copy
}
// Convert from unicode
DWORD charlength = (length * sizeof(char));
char * pMBString = (char *) LocalAlloc(LPTR, charlength+sizeof(char));
wcstombs(pMBString, pString, charlength);
CreateDirectory(L"\\Travel Manager", NULL);
Page 276
HANDLE hFile;
hFile = CreateFile(L"\\Travel Manager\\Notes.txt", GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwWritten;
if (hFile > 0)
{
WriteFile(hFile, pMBString, charlength, &dwWritten, NULL);
CloseHandle(hFile);
}
LocalFree(pString);
#endif
}
When the TravelManager application is started, it automatically looks for this saved data file and reads the contents into the
Notes view. After creating the view, the Create method of the NotesView class then tries to open an existing notes.txt file in
the TravelManager directory. If successful, the Create method uses the GetFileSize function to determine the size of a buffer
needed to hold the contents of the file. The Create method creates the appropriate buffer, reads the contents into the buffer with
the ReadFile function, and converts the string to Unicode with the mbstowcs function. Finally, the Create method adds the text
to the edit control in the Notes view.
BOOL NotesView::Create()
{
RECT rect;
GetClientRect(m_pMainWindow->m_hWnd, &rect);
rect.top += CommandBar_Height(m_pMainWindow->m_hwndCB);
Page 277
if (hFile > 0)
{
length = GetFileSize(hFile, NULL);
char *pMBString = (char *) LocalAlloc( LPTR , (length * sizeof(char) + size
ReadFile(hFile, pMBString, length*sizeof(char), &dwRead, NULL);
CloseHandle(hFile);
CHAPTER 10
Windows CE Database
Although Windows CE may eventually be used in many different devices, the
first Handheld PCs will more than likely be used as personal information mana
gement devices. The standard Windows CE applications will enable the user to
manage appointments, phone numbers, and tasks. Commercial Windows CE
applica tions will do a range of tasks,from managing expenses and finances to
creating grocery lists.
It is easy enough for applications to manage their own data. Some applications
store their data in simple flat files, while other applications use full-fledged
relational databases. A unique situation with Windows CE applications,
however,is that they are likely extensions of desktop applications and should
share relevant data. Each application can be responsible for the management of
its own data and the synchronization of data between the desktop and the
Handheld device. This is such a common scenario with Windows CE, that
much of this functionality is built into the operating system.
Windows CE includes a full set of database functionality that frees every application from having to implement the same functionality. This database
functional- ity allows each application to create and maintain its own database
for user data. The calendar and task applications, for instance, that ship with
the Handheld PCs use their own database through this fun ctionality.
Page 280
The standardization of a database for Windows CE also enables applications to
easily share data. For instance, because the schedule application in Windows
CE maintains its data in a Windows CE database, other applications would be
able to access this information.
Windows CE Functions
PegCreateDatabase
PegDeleteDatabase
PegFindFirstDatabase,
PegFindNextDatabase
PegOpenDatabase
PegSeekDatabase
PegReadRecordProps
PegWriteRecordProps
PegOidGetInfo
PegSetDatabaseInfo
Page 282
Records and Properties
Records and properties are the building blocks of Windows CE databases. A
database is comprised of a number of records, and each record is comprised of
one or more properties.
Every record in a Windows CE database is identified by a unique object iden
tifier. This object identifier is assigned by the system when a new record is
created. Although an application need not keep track of the record identifiers,
they can be used in seeking a database to get to a specific record. The record
object identifier is of type PEGOID.
Each property of a given record consists of the property identifier, data type,
and data value. The property identifier and data type are combined into a
two-part, double word value of type PEGPROPID. The high-order word is an
application-defined identifier, and The low-order word is a predefined constant
that specifies the property's data type. Windows CE supports integer, string,
time, and byte array ("blob") data types. The constants used to speci fy these
types are presented in Table 10.1.
Table 10.1
Windows CE Data Constants
Property Type Constant
PEGVT_BLOB
PEGVT_FILETIME
PEGVT_I2
PEGVT_I4
PEGVT_LPWSTR
PEGVT_UI2
Data Type
A PEGBLOB structure
A FILETIME structure
A 16-bit signed integer
A 32-bit signed integer
A null-terminated string
A 16-bit unsigned integer
PEGVT_UI4
Records are represented as an array of PEGPROPVAL structures that specify the record's
properties. The PEGPROPVAL structure is defined as follows:
typedef struct _PEGPROPVAL {
PEGPROPID propid;
WORD wLenData;
WORD wFlags;
PEGVALUNION val;
} PEGPROPVAL;
The PEGPROPVAL structure has the following members:
PEGPROPID propid. Specifies the identifier of the property value where the high-order
word is an application-defined value, and the low-order word is a PEGVT_ constant that
specifies the data type.
WORD wLenData. Not currently used.
WORD wFlags. Flag set by an application to PEGDB_PROPDELETE to specify the
property that is to be deleted, or set by the system to PEGDB_PROPNOTFOUND when
updating a record where the specified property is not found.
PEGVALUNION val. Specifies the actual value for simple types, or a pointer for strings
or BLOBs.
An array of PEGPROPVAL structures is used when both reading and writing records. When
reading records, for example, an application can use the TypeFromPropID function to determine
the property type given to the property identifier (PEGPROPID).
Creating and Deleting Databases
Applications can create and delete databases as needed. The number of databa ses that can exist
is limited only by available memory (object store space) on the device.
Page 284
Windows CE databases are created with the PegCreateDatabase function. The parameters to the
function include the name and type identifier for the data base and the optional sort order
specifications. The sort order specifications specify the number of sort orders active in the
database, with four being the maximum possible. This parameter can be zero if no sort orders are
active.
The following table summarizes the parameters to PegCreateDatabase.
PegCreateDatabase Parameter
LPWSTR lpszName
DWORD dwDbaseType
WORD wNumSortOrder
SORTORDERSPEC *
rgSortSpecs
Description
The name of the database,
which can be up to 32
characters long.
The application-defined type
of the database.
Number of sort orders in the
rgSortSpecs array. A database
can have zero to four sort
orders.
Pointer to array of sort order
descriptions or NULL if zero
specified for
wNumSortOrder.
If PegCreateDatabase is successful, the return value is the object identifier (PEGOID) of the
database. The database object identifier is used to open a database in order to manipulate its
contents. If the PegCreateDatabase function fails, the return value is NULL. The GetLastError
function can be used to get a specific error code. Possible error codes for PegCreateDatabase are
listed in the following table.
Error Code
Description
The object store does not contain
ERROR_DISK_FULL enough space to create the new
database.
Page 285
Error Code
Description
ERROR_INVALID_ PARAMETER A parameter is invalid.
A database already exists
ERROR_DUP_NAME
with the specified name.
The PegDeleteDatabase function is used to destroy a database. The only parameter to the
function is a PEGOID, which is the object identifier of the database to be deleted. If the
PegDeleteDatabase function succeeds, the return value is TRUE; otherwise, it is FALSE. The
GetLastError function can be used to get extended error information. Possible error codes are
ERROR_INVALID_PARAMETER, meaning a parameter was invalid, or ERROR_SHARING
_VIOLATION,meaning another thread has an open handle to the database.
Enumerating Databases
The Windows CE object store can contain an arbitrary number of databases. The
PegFindFirstDatabase and PegFindNextDatabase functions enable an application to enumerate
the databases in the object store.
The PegFindFirstDatabase begins the enumeration sequence and returns a handle to the
enumeration context. This handle is used with the PegFindNextDatabase function to obtain the
object identifiers for each database. At the end of the enumeration, PegFindNextDatabase returns
the extended error value ERROR_NO_MORE_ ITEMS.
HANDLE hEnumerator;
PEGOID objectID;
hEnumerator = PegFindFirstDatabase(0);
if (hEnumerator == INVALID_HANDLE_VALUE)
{
::MessageBox(NULL, L"Invalid handle", L"Error", MB_OK);
return;
}
while( (objectID = PegFindNextDatabase(hEnumerator)) != 0)
{
// use the objectID of database
...
}
CloseHandle(hEnumDB); // must close handle to enumeration context
Page 287
Opening Databases
In order to access a Windows CE database, an application must first obtain a handle to the
database. This handle is then used in other database API func tions. The PegOpenDatabase
function is used to open a Windows CE database.
To identify the database to open, an application can specify either a data base name or a database
object identifier. The return value of the PegOpenData base function is a handle to the opened
database. That handle is then used in subsequent calls to read or modify the database. When an
application is finis hed using the database, it must close the handle by calling the CloseHandle
function.
PPEGOID poid
LPWSTR lpszName
PEGPROPID propid
DWORD dwFlags
Description
Points to the object identifier of the
database to be opened. To open a
database by name, set the value
pointed to by poid to zero, which will
enable it to receive the object identifier
of the newly opened database when a
database name is specified for
lpszName.
Points to the name of the database to
be opened. This parameter is ignored if
the value pointed to by poid is
non-zero.
Specifies the property identifier of the
primary key for the sort order in which
the database is to be traversed. All
subsequent calls to PegSeekDatabase
assume this sort order. This parameter
can be zero if the sort order is not
important.
Specifies an action flag of either
PEGDB_AUTOINCREMENT or 0.
HWND hwndNotify
Page 289
If the PegOpenDatabase function succeeds, the return value is a handle to the
open database. If the function fails, the return value is
INVALID_HANDLE_VALUE. To get extended error information, call
GetLastError. The extended error may be one of the error codes listed in the
following table.
Error Code
Description
A parameter was
ERROR_INVALID_PARAMETER
invalid.
No database exists with
the specified name.
This error code applies
only if the value
ERROR_FILE_NOT_FOUND
pointed to by poid was
set to NULL (or zero)
when the function was
called.
No memory was
ERROR_NOT_ENOUGH_MEMORY available to allocate a
database handle.
Sorting Databases
An application normally puts the same kind of information in every record in a
given database. Each record in the TravelManager application might contain
the airline, flight number, departure time, arrival time, seat number, and so on.
In addition, the same property for each record would have the same property
identifier (for example, the property identifier for the flight number property of
one record would be the same for all other records in that database).
When all the records in a Windows CE database share the same property
identifiers, an application can request that the system sort the records based on
a given property. The order in which the records are sorted affects the order in
which the database seeking function
Page 290
PegSeekDatabase finds records in the database, or the order in which the
system advances the seek pointer when using the
PEGDB_AUTOINCREMENT flag when opening a database.
Meaning
The sort is done in
descending order. By
PEGDB_SORT_DESCENDING
default, the sort is done
in ascending order.
The sort operation is
case sensitive. This
PEGDB_SORT_CASEINSENSITIVE
value is valid only for
strings.
Records that do not
contain this property
are placed before all the
PEGDB_SORT_UNKNOWNFIRST other records. By
default, such records
are placed after all
other records.
Page 291
An application specifies which sort order to use when it calls the
PegOpenDatabase function to open a handle to the database. Only one sort
order can be active for each open handle. However, by opening multiple
handles to the same database, an application can use more than one sort order.
The possible sort orders for a database are defined when the database is
created. An application can change the sort orders for a database after it has
been created using the PegSetDatabaseInfo function. However, because the
system must revise internal indices it uses to maintain the sort orders, changing
sort orders can use a large amount of system resources and may take
considerable time to complete.
Seeking and Searching Records
Records in a database are retrieved from wherever the database's
seek pointer currently points to. Therefore, an application must seek the
desired record before attempting to read or modify data. The PegSeekDatabase
function is used to seek a specified record in an open database. The desired
record can be specified by its object identifier or by a relational value, such as
its "name" property equal to "John Doe." When the PegSeekDatabase function
finds the desired record, the seek pointer is positioned at that record. An
application can then read or update that record.
The order in which the system finds records depends on the sort order that is
active with the open database handle. In other words, when searching for a
value of "John Doe," the system searches only the properties that have the
same property identifier as the sort order property identifier specified when
opening the database. If the Contacts is opened specifying the "Name"
property as the sort order, then searching for "John Doe" would search the
names. However, if the database was opened specifying the "Zip code" as the
sort order, then the same PegSeekDatabase call using "John Doe" would
examine all the Zip code properties for that value.
The following table summarizes the parameters to the PegSeekDatabase
function.
Page 292
PegSeekDatabase Parameter Description
Identifies the open database in
HANDLE hDatabase
which to seek.
Indicates the type of seek
DWORD dwSeekType
operation to perform.
Specifies a value to use for the
seek operation. The meaning of
DWORD dwValue
this parameter depends on the
value of dwSeekType.
Points to a variable that receives
the index from the start of the
LPDWORD lpdwIndex
database to the beginning of the
record that was found.
There are a variety of seek operations the PegSeekDatabase can perform. The
following table describes the possible values for the dwSeekType parameter of
the PegSeekDatabase function.
Seek Operation
PEGDB_SEEK_PEGOID
Description
Seeks until it finds an
object that has the given
object identifier specified
by the dwValue
parameter. This type of
seek operation is very
efficient.
Seek Operation
Description
returns zero. The
dwValue parameter is
a pointer to a
PEGPROPVAL
structure. The cost of
this type of operation
is O(n).
Seeks until it finds
the first value that is
equal to the given
value. If the seek
operation fails, the
seek pointer is left
pointing at the end of
PEGDB_SEEK_VALUEFIRSTEQUAL the database and the
function returns zero.
The dwValue
parameter is a pointer
to a PEGPROPVAL
structure. The cost of
this type of operation
is O(n).
Starting from the
current seek position,
seeks exactly one
position forward in
the sorted order and
checks if the next
record is equal in
value to the given
PEGDB_SEEK_VALUENEXTEQUAL
value. If so, returns
the object identifier of
the next record;
otherwise, returns
zero and leaves the
seek pointer at the
end of the database.
This operation can be
continues
Page 294
Seek Operation
Description
used in conjunction with
the PEGDB_SEEK_
VALUEFIRSTEQUAL
operation to enumerate
all records with an equal
value. The dwValue
parameter specifies the
value for which to seek.
This is a O(1) operation.
Seeks until it finds a
value greater than or
equal to the given value.
If all records are smaller,
the seek pointer is left at
the end of the database,
PEGDB_SEEK_VALUEGREATER
and the function returns
zero. The dwValue
parameter is a pointer to a
PEGPROPVAL
structure. The cost of this
type of operation is O(n).
Seeks until it finds the
record at the given
position from the
beginning of the
database. The dwValue
PEGDB_SEEK_BEGINNING
parameter specifies the
number of the records to
seek, and the cost of this
type of operation is
O(dwValue).
Page 295
Seek Operation
Description
Seeks backward or forward from
the current position of the seek
pointer for the given number of
records. The dwValue parameter
specifies the number of records
from the current position. The
PEGDB_SEEK_CURRENT
function seeks forward if
dwValue is a positive value, or
backward if it is a negative value.
A forward seek operation is
efficient. The cost of a backward
seek is O(n).
Seeks backward for the given
number of records from the end
of the database. The dwValue
PEGDB_SEEK_END
parameter specifies the number of
records. The cost of this type of
operation is O(n).
If the PegSeekDatabase is successful, the return value is the PEGOID object identifier of the record. If the
search is not successful, the return value is zero. GetLastError may return ERROR_INVALID_PARAMETER
if a parameter is invalid.
Reading Records
After a database is opened, a fundamental operation is reading information. Data is read from a Windows CE database with the PegReadRecordProps function.
Page 296
Unlike the syntax of a SQL database, an application does not specify the set of records to be read (for
example, a "where" clause). Instead, the properties are read from the record at the current location of the seek
pointer. When a Windows CE database is opened, the seek pointer is positioned at the first record according to
the specified sort order. Additionally, if an application specified the PEGDB_AUTOINCREMENT flag when
opening the database, the seek pointer is incremented to the next record in the sort order after each call to the
PegReadRecordProps function.
The PegReadRecordsProps function is used to read multiple properties at one time. The application specifies
which properties to read through a parameter in the PegReadRecordProps function, which are specified in an
array of property identifiers (PEGPROPID). Another parameter specifies the number of property identifiers
that are listed in the array. Specifying NULL for the array tells the system to retrieve all the properties for the
current record.
Another parameter to the PegReadRecordProps function is a buffer for the results. The application specifies
the buffer into which the system is to write the property information and specifies a value indicating the size
of the buffer. Although it is possible for an application to call
PegReadRecordProps once to determine the size of the buffer necessary and then call the function again to
retrieve the data, the system greatly facilitates this common functionality. If the application specifies the
PEGDB_ALLOWREALLOC flag, the system will reallocate the buffer if it is too small to hold the property
information. If the application specifies NULL for the buffer, the system will allocate and use a buffer of the
correct size.
Although an application can read any number of properties from the current record, it is important to note that
the system stores records in compressed format and must decompress records before they are read. For
efficiency, an application should read all the desired properties in a single call rather than using several
separate calls.
If the PegReadRecordProps function is successful, the requested
property information is copied into the specified buffer. The resulting buffer consists of an array of
PEGPROPVAL structures. By using the
Page 297
PEGPROPID of each PEGPROPVAL structure, the application can determine the value for each property. For
property values that can vary in size, such as strings and BLOBs, the PEGPROPVAL structure contains a
pointer to the property's data. The data itself is positioned at the end of the allocated buffer.
If a requested property is not valid for the current record, the PEGPROPVAL structure for that property will
contain the PEGDB_PROPNOTFOUND flag.
The following table summarizes the parameters to the
PegReadRecordProps function.
PegReadRecordProps
Parameter
Description
HANDLE hDbase
DWORD dwFlags
LPWORD lpcPropID
Keyword
Brief
Full
Advanced
Search
Search Tips
PegReadRecordProps
Parameter
Description
Description
small to contain the data, this
parameter can be used to calculate
the amount of memory to allocate
for the buffer if
PEGDB_ALLOWREALLOC was
not specified.
If the PegReadRecordProps function is successful, the return value is the object identifier (PEGOID) of the record
that was read. If the function fails, the return value is zero. An application can use the GetLastError function to get
additional error information. GetLastError may return one of the error codes listed in the following table.
Error Code
Description
ERROR_INVALID_PARAMETER A parameter was invalid.
None of the requested
properties were found. The
ERROR_NO_DATA
output buffer and the size are
valid.
The given buffer was not
large enough, and the
reallocation failed (if the
PEGDB_ALLOWREALLOC
ERROR_INSUFFICIENT_BUFFER
flag was specified). The
lpcbBuffer parameter will
contain the required buffer
size.
The record that was about to
be read was deleted by
another thread. If the current
ERROR_KEY_DELETED
record was reached as a result
of an autoseek, this error is
not
continues
Page 300
Error Code
Description
returned, and the next record is
returned.
The current seek pointer is at
ERROR_NO_MORE_ITEMS
the end of the database.
An application must clean up memory allocated by the PegReadRecordProps function. However, because all
variable-length data is packed into the end of the result buffer, the only memory that must be freed is the original
pointer to the buffer passed in the call. Because it is possible for the function to fail but still have allocated memory
on the caller's behalf, an application must free the buffer pointer if it is non-NULL.
The following code sample demonstrates the process for reading properties from a Windows CE database.
PEGOID objId;
HANDLE hDb;
WORD cProps;
LPBYTE pBuf = NULL;
DWORD cbBuf = 0;
hDb = PegOpenDatabase(&objId,
// database object id
szDbName, // database name
0,
// no sort order
PEGDB_AUTOINCREMENT, // flags
NULL);
// no window for notifications
while (objId = PegReadRecordProps(hDb,
// database handle
PEGDB_ALLOWREALLOC, // allow reallocation
&cProps, // number of properties read
NULL,
// read all properties
&pBuf,
// property data buffer
&cbBuf)) // size of buffer
Page 301
{
//use the property values just read
}
CloseHandle(hDb); // close the database handle hDb
Writing Records
Data is written to a Windows CE database with the PegWriteRecordProps function. This function can be used to
create new database records or to modify existing records.
As discussed previously, a record is composed of a set of properties. To write these properties to a database record,
an application composes an array of PEGPROPVAL structures. Each PEGPROPVAL structure specifies a single
property identifier and a corresponding value for that property.
The PegWriteRecordProps function writes all the requested properties into the specified record. As with reading
properties from records, an application should write all of a record's properties at one time due to the overhead
encountered when data is saved to the database in a compressed format.
The PegWriteRecordProps function is used to create new database records and also to modify existing database
records. If the record identifier parameter to the function specifies an existing record, the function updates the
properties for that record. If the record identifier parameter is 0, a new record is added to the database with the
specified properties. The PegWriteRecordProps function does not utilize or move the seek pointer.
An application can also delete an existing property to a record. Specifying the PEGDB_PROPDELETE flag in the
PEGPROPVAL structure instructs the PegWriteRecordProps function to remove the given property.
The following table summarizes the parameters to the PegWriteRecordProps function.
Page 302
PegWriteRecordProps Parameter Description
Identifies an open database.
The database must have been
HANDLE hDbase
opened by a previous call to
the PegOpen Database
function.
Identifies the record to which
the given properties are to be
written. If this parameter is
PEGOID oidRecord
zero, a new record is created
and filled in with the given
properties.
Indicates the number of
properties in the array
WORD cPropID
specified by the rg PropVal
parameter. The cPropID
parameter must not be zero.
Points to an array of PEG
PROPVAL structures that
PEGPROPVAL * rgPropVal
specify the property values to
be written to the given
record.
If the PegWriteRecordProps function succeeds, the return value is the object identifier of the record to which the
properties were written. If the function fails, the return value is zero. An application can use the GetLastError
function to get additional error information.
GetLastError may return one of the error codes listed in the following table.
Error Code
Description
There was not enough
ERROR_DISK_FULL
space in the object store
to write the properties.
ERROR_INVALID _PARAMETER A parameter was invalid.
Page 303
The following code sample demonstrates the process for writing a record to a Windows CE database.
PEGPROPVAL NewProp;
// the new property contains a blob...
PEGBLOB blob;
// the blob contains a byte array...
BYTE * pBuf = NULL; // ...and here's the actual blob data
UINT cbBuf;
// count of bytes needed in blob
...
// figure out the size needed, then allocate it
pBuf = (BYTE *) LocalAlloc(LMEM_FIXED, cbBuf);
// put the actual data into pBuf here...
// now set up to write the new blob property
NewProp.propid = PEGVT_BLOB;
NewProp.wFlags = 0;
NewProp.val.blob = blob; // blob itself points to the buffer
blob.dwCount = cbBuf; // count of bytes in the buffer
blob.lpb = pBuf; // set PEGBLOB field to point to buffer
oid = PegWriteRecordProps(hDb, // database handle
0, // new record
1, // one property
&NewProp); // pointer to the blob property
// perform error handling by checking oid...
Deleting Records
An application uses the PegDeleteRecord function to delete a record from a database, supplying the object identifier
of the record and the handle to the open database that contains the record. The following table summarizes the
available parameters for the PegDeleteRecord function.
PegWriteRecordProps Description Parameter
Identifies the database from which the
record is to be deleted. To delete a
hDatabase
record, the database must be open. An
application opens a database by calling
the PegOpenDatabase function.
continues
Previous | Table of Contents | Next
};
} PEGOIDINFO;
Page 305
The PEGOIDINFO structure has the following members:
WORD wObjType. Specifies the type of the object. This parameter can be
one of the following values:
Object Type
Description
The object store contains no valid
OBJTYPE_INVALID
object that has this object identifier.
OBJTYPE_FILE
The object is a file.
OBJTYPE_ DIRECTORY The object is a directory.
OBJTYPE_ DATABASE The object is a database.
The object is a record inside a data
OBJTYPE_RECORD
base.
Page 306
The PEGFILEINFO structure is defined as follows:
Description
The szDbaseName member is
valid and should be used.
The dwDbaseType member is
valid and should be used.
PEGDB_VALIDSORT SPEC
Page 308
DWORD dwDbaseType. Specifies a type identifier for the database.
WORD wNumRecords. Specifies the number of records in the database.
WORD wNumSortOrder. Specifies the number of sort orders active in the
database. Up to four sort orders can be active at a time.
DWORD dwSize. Size, in bytes, that the database is using.
FILETIME ftLastModified. Last time this database was modified.
SORTORDERSPEC rgSortSpecs. Specifies the number of actual sort
order descriptions. Only the first n array members are valid, where n is the
value specified by the wNumSortOrder member.
Setting Database Information
Certain database information can be changed for an existing database. An
application can change the database name, database type, and sort order
descriptions for any database. The PegSetDatabaseInfo function is used to
change database information. The following table lists
PegSetDatabaseInfo parameters. Description
Specifies the object identifier
PEGOID oidDbase
of the database for which
parameters are to be set.
Points to a PEGDBASEINFO
structure that contains new
parameter information for the
PEGDBASEINFO * pNewInfo
database. The wNumRecords
member of the structure is not
used.
Page 309
An application specifies the database information to be changed by setting the
appropriate fields in the PEGDBASEINFO structure. The PEGDBASEINFO
structure is described in the "Retrieving Object Information" section of this
chapter.
The return value from PegSetDatabaseInfo is TRUE if the function succeeds and
FALSE otherwise. The GetLastError function can return the extended error
codes listed in the following table.
Error Code
Description
ERROR_INVALID_ PARAMETER A parameter was invalid.
Go!
Keyword
Brief
Full
Advanced
Search
Search Tips
Description
DB_PEGOID_
Another thread modified an object in the object store
CHANGED
DB_PEGOID_
Another thread created an object identifier in the object store
CREATED
DB_PEGOID_
RECORD
Another thread deleted a record
_DELETED
WPARAM LPARAM
PEGOID:
identifier
of the
modified
object
PEGOID:
identifier
of the
parent
object
PEGOID:
PEGOID: identifier
created
of the of
object
the parent
object
PEGOID: PEGOID:
identifier identifier
of the
of the
deleted
parent
object
object
Contacts Database
One of the standard applications included with Windows CE is the Contacts application. This application tracks such information
as names, addresses, and phone numbers. The Contacts application stores all of the contact data in a Windows CE databasethe
Contacts database.
By storing data in a Windows CE database, the Contacts application makes its information available to other applications. If an
application
Page 311
permits the user to enter a name, the application could then search the Contacts database for other relevant information about that
name.
An application could use the standard database API functions, such as PegOpenDatabase, PegReadRecordProps, and so on, to
retrieve information from the Contacts database. However, Windows CE also includes a special set of functions and structures that
an application can use to query and manipulate the contents of the Contacts database. The Contact database API functions are
listed in the Table 10.4.
Table 10.4
Contact APIs
Function
Description
Adds an address card to the
AddAddressCard
Contacts database
CloseAddressBook
Closes the Contacts database
CreateAddressBook
Creates the Contacts database
Removes an address card from the
DeleteAddressCard
Contacts database
Frees memory allocated for an
FreeAddressCard
address card
Retrieves the position index of an
GetAddressCardIndex
address card
Retrieves the object identifier of
GetAddressCardOid
an address card
Retrieves the properties of an
GetAddressCardProperties
address card
Retrieves the property tags of
GetColumnProperties
columns that can be used to sort
the Contacts database
Searches the name property of all
address cards in the Contacts
GetMatchingEntry
database for a name matching a
specified string
Returns the number of address
GetNumberOfAddressCards
cards in the Contacts database
continues
Page 312
Table 10.4
Contact APIs, continued
Function
Description
Retrieves information about a property
GetPropertyDataStruct
in the Contacts database
Retrieves the order in which the
GetSortOrder
Contacts database is currently sorted
Modifies an address card in the
ModifyAddressCard
Contacts database
OpenAddressBook
Opens the Contacts database
Opens an address card and retrieves its
OpenAddressCard
properties
Recounts the number of address cards
RecountCards
in the Contacts database
Specifies the columns that can be used
SetColumnProperties
to sort the Contacts database
SetMask
SetSortOrder
Address Cards
As with any Windows CE database, the Contacts database is comprised of a set of records. For the purposes of the Contacts
database API functions, records in the Contacts database are referred to as address cards. Each address card contains a set of
properties that define information about that particular entry.
All address cards contain the same set of predefined properties. The properties include addresses, phone numbers, and birthdays.
Each address card property has an associated identifier called a property tag. The property tag requests specific address card
information and identifies the information that is returned. The following list assembles the Contacts database property tag
identifiers:
Page 313
HHPR_ANNIVERSARY
HHPR_ASSISTANT_NAME
HHPR_ASSISTANT_TELEPHONE_NUMBER
HHPR_BIRTHDAY
HPR_BUSINESS_FAX_NUMBER
HHPR_CAR_TELEPHONE_NUMBER
HHPR_CATEGORY
HHPR_CHILDREN_NAME
HHPR_COMPANY_NAME
HHPR_DEPARTMENT_NAME
HHPR_EMAIL1_EMAIL_ADDRESS
HHPR_EMAIL2_EMAIL_ADDRESS
HHPR_EMAIL3_EMAIL_ADDRESS
HHPR_GENERATION
HHPR_GIVEN_NAME
HHPR_HOME2_TELEPHONE_NUMBER
HHPR_HOME_ADDRESS_CITY
HHPR_HOME_ADDRESS_COUNTRY
HHPR_HOME_ADDRESS_POSTAL_CODE
HHPR_HOME_ADDRESS_STATE
HHPR_HOME_ADDRESS_STREET
HHPR_HOME_FAX_NUMBER
continues
Page 314
HHPR_HOME_TELEPHONE_NUMBER
HHPR_MIDDLE_NAME
HHPR_MOBILE_TELEPHONE_NUMBER
HHPR_NAME_PREFIX
HHPR_NOTES
HHPR_OFFICE_ADDRESS_CITY
HHPR_OFFICE_ADDRESS_COUNTRY
HHPR_OFFICE_ADDRESS_POSTAL_CODE
HHPR_OFFICE_ADDRESS_STATE
HHPR_OFFICE_ADDRESS_STREET
HHPR_OFFICE_LOCATION
HHPR_OFFICE_TELEPHONE_NUMBER
HHPR_OFFICE2_TELEPHONE_NUMBER
HHPR_OTHER_ADDRESS_CITY
HHPR_OTHER_ADDRESS_COUNTRY
HHPR_OTHER_ADDRESS_POSTAL_CODE
HHPR_OTHER_ADDRESS_STATE
HHPR_OTHER_ADDRESS_STREET
HHPR_PAGER_NUMBER
HHPR_SPOUSE_NAME
HHPR_SURNAME
HHPR_TITLE
Page 315
HHPR_WEB_PAGE
HHPR_LAST_FIRST_NAME
HHPR_FIRST_LAST_NAME
HHPR_HOME_ADDRESS
HHPR_OTHER_ADDRESS
HHPR_OFFICE_ADDRESS
HHPR_EMAIL_TYPE
HHPR_EMAIL_OR_PAGER_TYPE
Opening the Contacts Database
Before accessing information in the Contacts database, an application must first open the database. The OpenAddressBook
function is used to open the Contacts database. As when opening other Windows CE databases, the OpenAddressBook function
allows the application to specify a sort order and a window handle to receive notifications about changes made to the Contacts
database.
Because the Contacts database is not created until the Contacts application is used, it is quite possible that the call to
OpenAddressBook will fail. If the Contacts database does not yet exist and the application wants to add data to it, any application
can create the Contacts database with the CreateAddressBook function. When creating the Contacts database, up to four sort
orders can be specified. If an application does not specify sort order in the CreateAddressBook function, the system assigns the
default sort order of HHPR_SURNAME, HHPR_COMPANY_NAME,
HHPR_OFFICE_TELEPHONE_NUMBER,
HHPR_HOME_TELEPHONE_NUMBER.
When an application is finished using the Contacts database, it must call the CloseAddressBook function.
Page 316
Accessing Address Cards
In order to access the properties for an address card, it is necessary to have the object identifier of the desired address card. Each
address card has a unique object identifier, which is assigned by the system when the address card is created. In addition to the
object identifier, each address card has a position index. The position indices of the address cards
are based on the current sort order of the database. The functions GetAddressCard Oid and GetAddressCardIndex can be used to
get the object identifier or the posit ion index if an application has one of those values.
An application can search for an address card with the GetMatchingEntry function. This function searches for a given value in any
one of the address card properties regardless of the current sort order for the database.
After an application obtains the object identifier for the desired address card, it can use the OpenAddressCard or
GetAddressCardProperties function to retrieve the current properties for the address card. Both functions fill an AddressCard
structure with the requested card's properties. Using the OpenAddressCard function retrieves all the properties for the address card,
while using the GetAddressCardProperties retrieves only a specified set of properties. If only a few properties from the address
card are needed, calling GetAddressCardProperties uses less memory than OpenAddressCard.
The AddressCard structure contains the values for the properties of the address card. The structure is defined as follows:
typedef struct _AddressCard {
// System time members
SYSTEMTIME stBirthday;
SYSTEMTIME stAnniversary;
// Business view fields
TCHAR *pszBusinessFax;
TCHAR *pszCompany;
TCHAR *pszDepartment;
TCHAR *pszEmail;
TCHAR *pszMobilePhone;
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
TCHAR *pszOfficeLocation;
TCHAR *pszPager;
TCHAR *pszWorkPhone;
TCHAR *pszTitle;
// Personal view fields
TCHAR *pszHomePhone;
TCHAR *pszEmail2;
TCHAR *pszSpouse;
// Notes view fields
TCHAR *pszNotes;
// Other fields the user can select
TCHAR *pszEmail3;
TCHAR *pszHomePhone2;
TCHAR *pszHomeFax;
TCHAR *pszCarPhone;
TCHAR *pszAssistant;
TCHAR *pszAssistantPhone;
TCHAR *pszChildren;
TCHAR *pszCategory;
TCHAR *pszWebPage;
TCHAR *pszWorkPhone2;
// Name fields
TCHAR *pszNamePrefix;
TCHAR *pszGivenName;
TCHAR *pszMiddleName;
TCHAR *pszSurname;
TCHAR *pszGeneration;
// Address Fields
TCHAR *pszHomeAddrStreet;
TCHAR *pszHomeAddrCity;
TCHAR *pszHomeAddrState;
TCHAR *pszHomeAddrPostalCode;
TCHAR *pszHomeAddrCountry;
TCHAR *pszOtherAddrStreet;
TCHAR *pszOtherAddrCity;
Page 318
TCHAR *pszOtherAddrState;
TCHAR *pszOtherAddrPostalCode;
TCHAR *pszOtherAddrCountry;
TCHAR
TCHAR
TCHAR
TCHAR
TCHAR
*pszOfficeAddrStreet;
*pszOfficeAddrCity;
*pszOfficeAddrState;
*pszOfficeAddrPostalCode;
*pszOfficeAddrCountry;
BYTE *rgbReserved[84]
} AddressCard;
When an application is finished using the data in the AddressCard structure, it must call theFreeAddressCard function to
free the memory allocated in the system for the address card data. For every callto OpenAddressCard and GetAd
dressCardProperties, there must be a corresponding call to FreeAddressCard.
Adding or Modifying Address Cards
Address card data is added or modified with the same AddressCard structure used to retrieve data from an address card.
To create a new address card, an application fills an AddressCard structure with the values for the card's properties. The
application then calls the SetMask function for each of the properties that have valid data set in the AddressCard
structure. Finally, the application calls the AddAddressCard function to create the new address card.
Modifying an existing address card uses a similar procedure. The application starts by filling an AddressCard structure
with the current properties by using the GetAddressCardProperties or OpenAddressCard functions. It then modifies the
desired properties and calls SetMask for each one. Finally, the application calls ModifyAddressCard to commit the
address card changes to the database.
To completely remove an address card from the Contacts database, an application can use the DeleteAddressCard
function.
Page 319
Page 320
PPEGPROPVAL pPegPropVal;
LV_ITEM lvi;
lvi.mask = LVIF_TEXT;
lvi.iSubItem = 0;
// Find database to open by name
pegOid = 0;
// Use the date field for sort order
pegpropid = MAKELONG( PEGVT_FILETIME, 0);
hDB = PegOpenDatabase(&pegOid, TEXT("TravelManager Database"),
pegpropid, PEGDB_AUTOINCREMENT, NULL);
if ( hDB == INVALID_HANDLE_VALUE)
{
// Could get extended error info with PegGetLastError
return FALSE;
}
row = 0;
while ( (PegRecObj = PegReadRecordProps(hDB, PEGDB_ALLOWREALLOC,
&wNumRecProps, NULL, &lpRecProps, &cbRecProps)) != 0)
{
if ( lpRecProps )
{
if ( wNumRecProps )
{
pPegPropVal = (PPEGPROPVAL)lpRecProps;
// add each property to the table
for ( i= 0 ; i < wNumRecProps; i++)
{
switch (HIWORD(pPegPropVal[i].propid))
{
case 0:
FileTimeToSystemTime(&(pPegPropVal[i].val.filetime), &SystemTime);
wsprintf(szBuf, TEXT("%d/%d"), SystemTime.wMonth, SystemTime.wDay);
lvi.iItem = row;
lvi.pszText = szBuf;
Page 321
lvi.cchTextMax = 6;
ListView_InsertItem(hwndLV, &lvi);
break;
case 1:
wsprintf(szBuf, TEXT("%d"), pPegPropVal[i].val.uiVal);
ListView_SetItemText(hwndLV, row, 1, szBuf);
break;
case 2:
ListView_SetItemText(hwndLV, row, 2, pPegPropVal[i].val.lpwstr);
break;
case 3:
ListView_SetItemText(hwndLV, row, 3, pPegPropVal[i].val.lpwstr);
break;
case 4:
FileTimeToSystemTime(&(pPegPropVal[i].val.filetime), &SystemTime);
wsprintf(szBuf, TEXT("%d/%d"), SystemTime.wMonth, SystemTime.wDay);
ListView_SetItemText(hwndLV, row, 4, szBuf);
break;
case 5:
FileTimeToSystemTime(&(pPegPropVal[i].val.filetime), &SystemTime);
wsprintf(szBuf, TEXT("%d/%d"), SystemTime.wMonth, SystemTime.wDay);
ListView_SetItemText(hwndLV, row, 5, szBuf);
break;
case 6:
ListView_SetItemText(hwndLV, row, 6, pPegPropVal[i].val.lpwstr);
break;
}
}
}
LocalFree(lpRecProps);
}
// increase row and reset other parameters
row++;
cbRecProps = 0;
Page 322
lpRecProps = NULL;
wNumRecProps = 0;
}
CloseHandle(hDB);
return TRUE;
}
TravelManager ApplicationWindows CE Databases
In the interest of space, the entire TravelManager application is not re-listed here. However, you can find the full
TravelManager application on the accompanying CD-ROM. See Appendix A, "Getting Started with the CD-ROM," for
information on accessing the files on the accompanying CD-ROM.
Page 323
Previous | Table of Contents | Next
CHAPTER 11
devices, providing endless online help is not realistic. Instead, the Windows
CE Pocket Help file for your application probably should include only
information on common tasks and key commands. More detailed information
then can be included in another form of documentation.
Page 326
When the help system is accessed through an applicationeither by tapping
the question mark button in the command bar or by using the Alt+H shortcut
keythe help file displayed is specified by the application.
A feature unique to the Windows CE help system is its ability to access other
help files from any help topic. The Pocket Help display window provides an
Other Help button that presents a list of all the help content files that exist in
the Windows folder. Selecting a help file from the list opens that Pocket Help
file. Figure 11.2 shows the Windows CE Pocket Help system listing the
available help files displayed after the user selects the Other Help button.
Figure 11.2
Results of selecting
the Other Help button.
Keyword
Brief
Full
Advanced
Search
Search Tips
<html>
<head>
<meta http-equiv=refer content="file:Calculator Help.htc">
</head>
<body>
<h6>Tips for using Calculator</h6>
You can use Calculator in two different views: Standard view and PopUp view.
<ul>
<li>In Standard view, Calculator uses on-screen buttons similar to the Windows 95 Calcu
<a href="file:cc_paper.htp">paper tape</a> that retains the last 100 lines of calculati
<li>In <a href="file:cc_pop.htp">Pop-Up view</a>, Calculator shows only the entry box.
Calculator from this view, use the keyboard.
</ul>
<p>
</body>
</html>
Figure 11.4 shows the Help window displayed when the Calculator help file is opened and the Full Screen Mode button is
selected.
Page 331
Figure 11.4
Tips For Using
Calculator is
displayed in fullscreen mode.
Description
Comment
Hypertext link
Address (usually e-mail addresses)
Bold
Base font
Background sound
<BIG>
<BLINK>
<BLOCKQUOTE>
<BODY>
<BR>
<CAPTION>
<CENTER>
<CITE>
<CODE>
Big text
Blink text
Define quote
Document body
Line break
Table caption
Center text
Citation
Source code
continues
Previous | Table of Contents | Next
Page 333
Table 11.1
HTML Tags Supported in Pocket Help, continued
HTML Tag
<DD>
<DFN>
<DIR>
<DIV>
<DL>
<DT>
<EM>
<FONT>
<Hn>
<HEAD>
<HR>
<HTML>
<I>
<IMG>
<KBD>
<LI>
<LISTING>
<MENU>
<META>
<NOBR>
<OL>
<P>
<PLAINTEXT>
<PRE>
<S>
Description
Definition description
Definition
Directory list
Division
Definition list
Definition term
Emphasis
Font
Heading
Document head
Horizontal rule
HTML document
Italic text
Inline image
Keyboard
List item
Computer listing
Menu list
Meta
No break
Ordered list
Paragraph
Plain text
Preformatted text
Strikethrough text
Page 334
HTML Tag
<SAMP>
<SMALL>
<STRIKE>
<STRONG>
<SUB>
<SUP>
<TABLE>
<TD>
Description
Sample output
Small text
Strikethrough text
Strong emphasis
Subscript
Superscript
Table
Table data
<TH>
<TITLE>
<TR>
<TT>
<U>
<UL>
<VAR>
<WBR>
<XMP>
Table heading
Document title
Table row
Teletype text
Underlined text
Unordered list
Variable
Word break
Example
The following sections provide details on the HTML tags that are valid in Pocket Help files. The discussion of each tag
includes a description of the tag, the attributes that the tag can accept, and a small example of using the tag.
<!--COMMENTS-->
This tag is used to add comments to the HTML document that will be ignored by the Pocket Help display engine. The text
for the comments must be surrounded by the <!-- and the --> tags and cannot be nested, as shown in the following
example:
<!-- this is a comment -->
Page 335
<A>
The <A> tag designates an anchor element, which is a marked text that indicates the start and/or destination of a hypertext
link. The following list details the attributes of this tag:
HREF. Creates a hot-spot object that contains the HREF text from the anchor tag.
NAME. Creates a markup header with the value of the name property as the text.
The following is an example of the <A> tag:
<ADDRESS>
This tag displays text as italic, with a paragraph break before and after the text.
<ADDRESS>For more information, contact us at [email protected]
< ADDRESS>
<B>
This tag displays the text as bold.
This is <B>Bold</B> text.
<BASEFONT>
This tag defines the size of the font for the entire document, from the <BASEFONT> tag to the end.
The Size attribute sets the font size for which all sizes are based. This attribute has a valid range of 1_7.
Page 336
The following is an example of the <BASEFONT> tag:
<BASEFONT SIZE=6>This would be size 6 text.
<BGSOUND>
This tag instructs the application to play a background sound. Its attributes include the following:
SRC. Specifies URL of the sound.
LOOP. Loops the sound played.
The following is an example of the <BGSOUND> tag:
<BGSOUND SRC="tada.wav">
<BIG>
The <BIG> tag displays text in a larger font than the base font.
This is <BIG>Big</BIG> text.
<BLINK>
This tag turns the display of a block of text on and off.
<BLINK>This text would be blinking</BLINK>
<BLOCKQUOTE>
This tag formats a quotation.
<P>Then he said:
<BLOCKQUOTE>Windows CE is cool.</BLOCKQUOTE>
Page 337
<BODY>
The <BODY> tag indicates the start and end of the body, or the contents of the document immediately after the head.
See the contents and topic file examples at the beginning of this chapter for more information.
<BR>
This tag starts a new line of text.
<P>Once upon a midnight dreary<BR>While I pondered weak and weary<BR>Over many
volumes of forgotten lore<BR>
<CAPTION>
This tag adds a caption above or below a table. The <CAPTION> tag should be used inside the <TABLE> tag.
The ALIGN : top or bottom attribute enables the user to indicate placement of captions above or below a table.
<TABLE BORDER>
<CAPTION> Coordinates</CAPTION>
<TR><TH>X-Coordinate</TH><TH>Y-Coordinate</TH></TR>
<TR><TD>14</TD><TD>42</TD></TR>
</TABLE>
<CENTER>
The <CENTER> tag centers a line of text between the left margin and the right margin.
<CENTER>This line is centered.</CENTER>
Page 338
<CITE>
This tag indicates a citation, such as a book or the name of an expert, by emphasizing it, usually with italics
This code is from <CITE>Windows CE Programming</CITE>
<CODE>
This tag applies a computer code font (monospace) to the specified text.
This is <CODE>computer code</CODE> text.
<DD>
This tag identifies a description in a definition list and is used in conjunction with the <DL> and <DT> tags. See the
section on the <DL> tag for an example of this tag.
<DFN>
This tag identifies a definition term using emphasized text (italic).
The <DFN>DFN</DFN> tag identifies a defined term.
<DIR>
The <DIR> tag displays a short word list.
<DIR>
<LI>One
<LI>Two
<LI>Three
Page 339
<DIV>
The <DIV> tag marks the beginning of a new division or section in a document.
The attribute for the <DIV> tag is ALIGN : left, right, or center.
For an example of this tag, refer to the section on the <P> tag.
<DL>
This tag defines a glossary or definition list that is an automatically formatted two-column list with the terms on the left
and their definitions on the right. See also the sections on <DT> and <DD> for related information.
<DL>
<DT>HTML<DD>The Hypertext Mark-Up Language.
<DT>HTTP<DD>The Hypertext Transport Protocol.
</DL>
<DT>
This tag names a term in a definition list.
For an example of this tag, see the section on the <DL> tag.
<EM>
The <EM> tag emphasizes the specified text, usually with italic.
This is text with some <EM>Emphasis</EM>
<FONT>
This tag changes the size or typeface of the selected font.
Previous | Table of Contents | Next
<HEAD>
This tag begins (and ends) a part of the HTML document that refers to the document's
usage context. The <TITLE> and <META> tags generally are enclosed in the <HEAD>
tag.
<html>
<head>
<meta http-equiv=refer content="file:Calculator Help.htc">
</head>
<HR>
The <HR> tag inserts a horizontal rule line between the sections of a document. This tag
contains the following attributes:
SIZE. Indicates the height of the rule in pixels.
WIDTH. Indicates the width of the rule in pixels, or percentage of the currently
available page width. This can be reduced by images down the right and left sides of
the page.
ALIGN. Specifies left, right, or center positions.
NOSHADE. Indicates that the rule should be drawn as a solid bar, not in 3-D.
The following is an example of the <HR> tag:
<HR WIDTH=400 ALIGN=LEFT>
<HTML>
This tag defines an HTML document.
For an example of this tag, see the examples on the contents and topic files at the
beginning of this chapter.
Page 342
<I>
The <I> tag applies italics to the specified text.
This is <I>italicized</I> text.
<IMG>
This tag inserts an inline image in the document. The <IMG> tag contains the following
attributes:
<KBD>
The <KBD> tag applies a keyboard input font (monospace) to the specified text.
This is <KBD>keyboard input</KBD> text.
<LI>
The <LI> tag lists items with an ordered <OL>, unordered <UL>, menu <MENU>, or
directory <DIR> list. This tag contains the following attributes:
TYPE. Indicates that a number or bullet style will be set in an ordered or unordered
list, respectively.
VALUE. Specifies a numeric starting value in an ordered list.
The following is an example of the <LI> tag:
<OL>
<LI>First
<LI>Second
<LI>Third
</OL>
<LISTING>
This tag applies a computer listing font (monospace) to the specified text.
<LISTING>This is text in the listing style</LISTING>
<MENU>
This tag displays a menu list of items and is used in the Contents page of a Pocket Help
file.
<menu>
Page 344
<li><a href="file:cc_basic.htp">Tips for using Calculator</a>
<li><a href="file:cc_paper.htp">Using the paper tape</a>
<li><a href="file:cc_pop.htp">Working in Pop-Up view</a>
</menu>
<META>
The <META> tag provides information about the current document and is used in Pocket
Help topic files to specify the contents file for this help topic.
This tag contains the attribute HTTP-EQUIV, which specifies the referring contents file.
The following is an example of the <META> tag:
<meta http-equiv=refer content="file:Calculator Help.htc">
<NOBR>
The <NOBR> tag turns off the automatic word wrap and line breaks.
<NOBR>Word wrap and line breaks are turned off</NOBR>
<OL>
The <OL> tag starts an ordered (numbered) list. This tag contains the following attributes:
START. Indicates a numeric starting value.
TYPE. Indicates A (uppercase letters), a (lowercase letters), I (uppercase Roman
numerals), i (lowercase Roman numerals), 1 (Arabic numbers).
Page 345
The following is an example of the <OL> tag:
<OL>
<LI>Choice 1
<LI>Choice 2
<LI>Choice 3
</OL>
<P>
The <P> tag indicates the start of a new paragraph. It contains the ALIGN attribute, which
<PLAINTEXT>
This tag applies a monospace font to the specified text.
<PLAINTEXT>This is plain text.</PLAINTEXT>
<PRE>
The <PRE> tag applies a monospace font to one or more lines of preformatted text and
maintains the character and space formatting of the text. This tag contains the WIDTH
attribute, which indicates the maximum line width.
The following is an example of the <PRE> tag:
<PRE>
This
text
is a
column.</PRE>
Page 346
<S>
The <S> tag is the same as the <STRIKE> tag. Refer to <STRIKE> in the following text
for information.
<SAMP>
This tag applies a sample program output font (monospace) to the specified text.
This is <SAMP>sample output</SAMP> text.
<SMALL>
This tag displays text in a smaller font than the default starting font.
This is <SMALL>small</SMALL> text.
<STRIKE>
This tag strikes through the specified text.
This is <STRIKE>Strikeout</STRIKE>text.
<STRONG>
The <STRONG> tag is the same as the bold, <B> tag sequence. Refer to the <B> tag
entry.
<SUB>
This tag moves the specified text below the base line on which the other text on the line
sits. The <SUB> tag also applies a smaller font.
H<SUB>2</SUB>O
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
<SUP>
The <SUP> tag moves the specified text above the base line on which the other text on the line sits. This tag also
applies a smaller font.
x<SUP>2</SUP> + y<SUP>2</SUP>
<TABLE>
This tag defines a table. It contains the following attributes:
BORDER. Indicates whether the table has a border or not.
CELLSPACING=<value>. Indicates the spacing, in pixels, between cells.
CELLPADDING=<value>. Indicates the spacing, in pixels, between the contents of the cells and the cell
borders.
WIDTH=<value_or_percent>. Specifies the width, in pixels, or the percent of the entire width of the table.
The following is an example of the <TABLE> tag:
<TABLE BORDER>
<CAPTION> Coordinates</CAPTION>
<TR><TH>X-Coordinate</TH><TH>Y-Coordinate</TH></TR>
<TR><TD>14</TD><TD>42</TD></TR>
</TABLE>
<TD>
The <TD> tag defines the data in the table cell.
<TABLE BORDER>
<CAPTION> Coordinates</CAPTION>
<TR><TH>X-Coordinate</TH><TH>Y-Coordinate</TH></TR>
<TR><TD>14</TD><TD>42</TD></TR>
</TABLE>
Page 348
<TH>
The <TH> tag defines a heading in a table cell and adds some emphasis (boldface).
<TABLE BORDER>
<CAPTION> Coordinates</CAPTION>
<TR><TH>X-Coordinate</TH><TH>Y-Coordinate</TH></TR>
<TR><TD>14</TD><TD>42</TD></TR>
</TABLE>
<TITLE>
This tag specifies a title for the document.
<TITLE>My Summer Vacation</TITLE>
<TR>
The <TR> tag defines a table row. This tag contains the following attributes:
ALIGN. Specifies center, left, or right positioning.
VALIGN. Specifies top, middle, or bottom positioning (the vertical alignment of the contents of the cells in the
row).
The following is an example of the <TR> tag:
<TABLE BORDER>
<CAPTION> Coordinates</CAPTION>
<TR><TH>X-Coordinate</TH><TH>Y-Coordinate</TH></TR>
<TR><TD>14</TD><TD>42</TD></TR>
</TABLE>
<TT>
The <TT> tag applies a teletype font (monospace) to the specified text.
This is <TT>teletype</TT> text.
Page 349
<U>
The <U> tag underlines the specified text.
This is <U>underlined</U> text.
<UL>
The <UL> tag starts an unordered (bulleted) list. This tag contains the following attributes:
TYPE. Specifies the type of bullet to be used (disc, circle, or square).
COMPACT. Suggests that the space between the bullet and the item be decreased.
The following is an example of the <UL> tag:
<UL>
<LI>Apple
<LI>Orange
<LI>Banana
</UL>
<VAR>
This tag indicates variable text by emphasizing it, usually with italic.
Use the <VAR>VAR</VAR> tag to highlight terms being introduced.
<WBR>
This tag inserts a line break within a no break <NOBR> line.
<XMP>
The <XMP> tag applies a monospace font to the specified text.
Here is an <XPM>example</XPM>
<TABLE BORDER>
<CAPTION ALIGN=TOP> The following table describes the information listed in the
table on the Air tab of the Itinerary View.</CAPTION>
<TR>
<TH>Table Column</TH>
<TH>Description</TH>
</TR>
<TR>
<TD>Date</TD>
<TD>Date of flight</TD>
</TR>
<TR>
<TD>Flight</TD>
<TD>Flight number</TD>
</TR>
<TR>
<TD>From</TD>
<TD>Origination city</TD>
</TR>
<TR>
<TD>To</TD>
<TD>Destination city</TD>
Page 352
</TR>
<TR>
<TD>Departs</TD>
<TD>Departure time</TD>
</TR>
<TR>
<TD>Arrives</TD>
<TD>Arrival time</TD>
</TR>
<TR>
<TD>Seat</TD>
<TD>Seat number</TD>
</TR>
</TABLE>
<p>
</body>
</html>
The other topic file provides an example of using a definition list:
<html>
<head>
<meta http-equiv=refer content="file:trvlmgr.htc">
</head>
<body>
<h5>TravelManager's Expenses View</h5>
<DL>
<DT>Expenses table<DD>Listing of all expenses that have been entered.
<DT>Today's Date<DD>The current date.
<DT>Add button<DD>Use to create a new expense entry.
<DT>Edit button<DD>Use to edit the selected expense entry.
CHAPTER 12
Description
Determines whether the application is
Load_AlreadyInstalled
already installed on the Handheld PC
Each of these application loader functions is detailed in the sections that follow.
Load_AlreadyInstalled
A setup application can use the Load_AlreadyInstalled function to determine if the specified
application is already installed on the target Handheld PC. The syntax of the function is as
follows:
BOOL bSuccess = Load_AlreadyInstalled( lpszAppName );
The lpszAppName in the preceding syntax is of type LPSTR and specifies the name of the
application to look for on the Handheld PC.
Page 356
The return value is a Boolean that indicates whether the application is already installed. A value of
FALSE indicates that the specified application is not currently installed on the Handheld PC. A
value of TRUE indicates that the application is currently installed, or that an error has occurred. A
value of TRUE is returned for an error to prevent accidental overwriting of the application.
Load_Exit
Upon completion of the entire loading process, the setup application must call the Load_Exit
function to end the loading process and stop the RPC service. The syntax of the function is as
follows:
Load_Exit();
The Load_Exit function takes no parameters and has no return value.
Load_Init
The Load_Init function initiates the loading process and must be called before any other Load
function. To communicate with the Handheld PC, the Load_Init function starts the Remote
Procedure Call (RPC) service. The syntax of the function is as follows:
LOADERROR dwSuccess = Load_Init();
The Load_Init function takes no parameters and returns a
LOADERROR. The return value can be either LOAD_SUCCESS or LOAD_FAILURE, which
indicates whether the initialization has succeeded.
Load_PegCpuType
The Load_PegCpuType function can be used by the setup application to determine the CPU type
of the target Handheld PC. This information might be necessary to decide which type of files to
copy to the device. The syntax of the function is as follows:
Page 357
char szCPUType[10];
BOOL bSuccess = Load_PegCpuType( &szCPUType );
The only parameter to the Load_PegCpuType function is a string buffer that is allocated and
deallocated by the caller. If successful, the function places one of the following strings in the
string buffer: either the SH3 string or the MIPS string.
The return value from Load_PegCpuType indicates whether the function is successful. A return
value of TRUE indicates success, while FALSE indicates that an error occurred or that the CPU
type of the device was unknown.
Note
For the Load_PegCpuType to be successful, the Handheld PC Explorer must have
connected to the target device at least once prior to making the Load_PegCpuType
function call.
Load_PegFreeSpace
The Load_PegFreeSpace function can be used to determine if enough free space exists on the
target device for the installation to proceed. The syntax of the function is as follows:
DWORD dwFreeSpace = Load_PegFreeSpace();
The return value from the Load_PegFreeSpace function is the amountin bytesof memory
remaining on the target Windows CE device.
Load_RegisterFileInfo
The Load_RegisterFileInfo function registers file information with Windows CE so that it can
display the correct file type and icon associated with an application's files. The syntax of the
function is as follows:
LOADERROR dwError = Load_RegisterFileInfo( szFileName, szIconFile,
szFileType, iIcon );
Page 358
The parameters to the Load_RegisterFileInfo function are detailed in the following list:
LPSTR szFileName. Application name with extension but without the path.
LPSTR szIconFile. Full path to the file name that contains the icon.
LPSTR szFileType. File type (currently not being used).
LPSTR iIcon. Index to the icon.
Load_RegisterFileInfo can have one of the following return values:
LOAD_SUCCESS. The process was successful.
Load
The Load function is the main function for downloading an application from the desktop PC to the
Windows CE device. In addition to loading application files, the Load function also adds
application information to the Windows CE registry and automatically creates an unload script for
the application. The Load function also can create a shortcut to the application and execute a
program on the Windows CE device before the loading process completes.
The Load function has the following syntax:
LOADERROR dwError = Load( hWindow, szCommandLine );
The first parameter to the Load function is a window handle that is used as the parent for any
windows created by the Load function. For instance, the window handle parameter is the parent of
the window
that indicates progress during the loading operation.
Previous | Table of Contents | Next
The second parameter to the Load function is the address of a buffer that
contains a list of command-line arguments. These command-line arguments
provide the information that ppcload.dll needs to load the application to the
target device. The seven command-line arguments that must be included in the
command-line string are detailed in the following list:
CPU type. The type of CPU on the target Windows CE device.
Currently, SH3 and MIPS are the only valid CPU types.
Application name. The name of the application being installed.
Install directory. The directory on the target Handheld PC where the
application will be stored.
Total bytes to copy. The number of bytes that will be copied to the
Handheld PC.
User name. The name of the person using the Windows CE device.
User company. The name of the user's organization.
Load file. The name of the load script file. Details of this file are
covered later in this chapter.
The command-line arguments must be arranged in a given order and separated
in the string buffer by spaces. If an argument must include a space, that
argument can be delimited by quotation marks.
The return value of the Load function is of type LOADERROR. The possible
values returned are detailed in the following list:
LOAD_SUCCESS. The action was successful.
LOAD_OUTOFSTORAGE. The device is out of memory.
LOAD_CANCELLEDBYUSER. The user canceled the loading process.
LOAD_INVALID_PARAMETER. The command line contains an
invalid parameter.
Page 360
string
When the copy command is used to copy .exe and .dll files from the desktop
PC to the Handheld PC, the source file on the desktop PC should have the
CPU type added as another extension to the filename. For instance, to copy a
file named sample.exe to an SH3 device, the file on the desktop PC should be
named sample.exe.sh3.
If the destination file already exists on the target device, the load process
displays a message box asking the user whether to overwrite the file.
All files copied to the target device with the copy command automatically are
added to the unload script for the application. These files then are removed
from the device when the user removes the application, or if an error occurs
during the loading process.
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
copyShared
The copyShared statement copies a shared file from the desktop PC to the Handheld PC. A
shared file is typically a DLL that is used by one or more applications. The syntax of the
command is as follows:
copyShared
sourceDirectory
destinationDirectory
filename
The arguments of the copyShared command are detailed in the following list:
sourceDirectory. Specifies the directory on the desktop PC that contains the files to be
copied. The specified directory is relative to the install directory. This argument can
be a period (.) to indicate that the source files are to be copied from the install
directory on the desktop PC.
destinationDirectory. Specifies the directory on the Handheld PC that receives the
files being copied. This parameter can specify an absolute or a relative path.
To specify an absolute path, this parameter must start with a backslash (\) to indicate
the root directory followed by the complete path. This command will fail if the
specified directory does not already exist on the Handheld PC.
To specify a relative path, this parameter can be a period (.). This indicates that the
source files are to be copied to the load directory on the Handheld PC. The load
directory is specified by the install directory argument of the Load function's
command-line parameter.
filename. Specifies the name of the file to copy.
Unlike the copy command, the copyShared command does not prompt the user if the
destination file already exists. Instead, if the destination directory already contains the file
specified by the file parameter, the file's time-stamp is compared to that of the source file.
The source file is copied only if it is newer than the destination file.
Page 365
Windows CE tracks the use of shared files through a reference count in the Windows CE
Registry. Every time the same shared file is copied to the target device, the reference count
for that file is incremented.
All files copied to the target device with the copyShared command automatically are added
to the unload script for the application. When an unload script that contains that shared file
is run, the reference count is decremented. When the count reaches zero, the file is removed.
Windows CE does not support the concept of a working directory, so DLLs for all
applications should be stored in the \Windows directory. If an application stores its DLLs in
another directory, it must load them explicitly using the LoadLibrary API command.
createShortcut
The createShortcut statement creates a shortcut in the Windows CE shell on the Handheld
PC and links the shortcut to an executable file. The syntax of the command is as follows:
createShortcut
directory
linkname
programDirectory
program
The arguments of the createShortcut command are detailed in the following list:
directory. Specifies the directory in which the shortcut is to be created. This argument
can be a period (.) to indicate that the shortcut is to be created in the load directory.
The load directory is specified by the install directory argument of the Load function's
command-line parameter.
linkname. Specifies the name of the link file (for example, sample.lnk).
programDirectory. Specifies the directory that contains the executable file to which
the shortcut is to be linked. This argument can be a period (.) to indicate that the file is
in the load directory on the Handheld PC.
program. Specifies the name of the executable file.
Page 366
Like the copied files, the shortcut information is added to the unload script for the
application. When the application is removed, the shortcut also is removed from the
Windows CE device.
execOnUnload
The execOnUnload statement adds the name of an executable file to the end of the unload
script. The file is executed when the unload script is run on the Handheld PC. The syntax of
the command is as follows:
execOnUnload
exefile
The argument of the execOnUnload command is exefile, which specifies the name of the
executable file to be added to the unload script.
exit
The exit statement causes execution of statements in the load file to cease. The syntax of the
command is as follows:
exit
No arguments to the exit command exist.
mkdir
The mkdir statement creates a directory in the Handheld PC file system. The syntax of the
command is as follows:
mkdir
directory
The argument of the mkdir command is directory, which specifies the name of the directory
to create. The directory can be an absolute path if the directory begins with a backslash (/). If
the directory name does not begin with an absolute path, the new directory is created with
the directory specified by the install directory argument of the Load function's
command-line parameter.
Page 367
prependToUnload
The prependToUnload statement adds a string to the front of the unload script. Because all
other load file statements automatically update the unload script, using this statement
generally is not necessary. The syntax of the command is as follows:
prependToUnload
string
The argument of the prependToUnload command is string, which specifies the string to add
to the unload script.
regInt
The regInt statement writes an integer in the value field of a registry key. The syntax of the
command is as follows:
regInt
key
subkey
bUninstall
value
integer
The arguments of the regInt command are detailed in the following list:
key. Specifies the root key that contains the key to receive the integer. This argument
can be the tilde character (~) to specify the "home" key
(HKEY_LOCAL_MACHINE\SOFTWARE\ Apps\your_app_name), or it can be one
of the following values: HKEY_CLASSES_ROOT, HKEY_CURRENT_USER,
HKEY_LOCAL_MACHINE,or HKEY_USERS.
subkey. Specifies the name of the key whose value field is to receive the integer.
bUninstall. Specifies whether the value should be added to the list of items to be
removed by the unload script. If this argument is set to one, the value will be removed
by the unload script. If set to zero, the registry value will remain even after the
application is uninstalled.
Previous | Table of Contents | Next
Page 368
value. Specifies the name of the value that is to receive the integer.
integer. Specifies the integer.
The bUninstall argument is ignored unless the tilde (~) character is used to specify the
home key in the key argument. This is to facilitate the anticipated future release of the
Application Manager, which will use the registry values under the home key to
determine user-defined preferences that should be saved if the program is uninstalled.
regKeyCreate
The regKeyCreate statement creates a key in the Handheld PC registry. The syntax of
the command is as follows:
regKeyCreate
key
subkey
bUninstall
The arguments of the regKeyCreate command are detailed in the following list:
key. Specifies the root key that contains the key to receive the integer. This
argument can be the tilde character (~) to specify the "home" key
(HKEY_LOCAL_MACHINE\SOFTWARE\ Apps\your_app_name), or it can be
one of the following values: HKEY_CLASSES_ROOT,
HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, or HKEY_USERS.
subkey. Specifies the name of the key to create.
bUninstall. Specifies whether the value should be added to the list of items to be
removed by the unload script. If this argument is set to one, the value will be
removed by the unload script. If set to zero, the registry value will remain even
after the application is uninstalled.
The bUninstall argument is ignored unless the tilde (~) character is used to specify the
home key in the key argument. This is to facilitate the anticipated future release of the
Application Manager, which will use the registry values under the home key to
determine user-defined preferences that should be saved if the program is uninstalled.
Page 369
The setup program should create all possible registry keys and values for the application
so they can be removed properly if the application is uninstalled.
regString
The regString statement writes a string in the value field of a registry key on the
Windows CE device. The syntax of the command is as follows:
regString
key
subkey
bUninstall
value
string
The arguments of the regString command are detailed in the following list:
key. Specifies the root key that contains the key to receive the integer. This
argument can be the tilde character (~) to specify the "home" key
(HKEY_LOCAL_MACHINE\SOFTWARE\ Apps\your_app_name), or it can be
one of the following values: HKEY_CLASSES_ROOT,
HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, or HKEY_USERS.
subkey. Specifies the name of the key whose value field is to receive the string.
This argument can be the tilde character (~) if the key argument is also a tilde.
Using the tilde character specifies no subkey and that the value receiving the
string is in the home key.
bUninstall. Specifies whether the value should be added to the list of items to be
removed by the unload script. If this argument is set to one, the value will be
removed by the unload script. If set to zero, the registry value will remain even
after the application is uninstalled.
value. Specifies the name of the value that is to receive the string.
string. Specifies the string. The characters %P are inserted in the string expand to
be the installation path on the Handheld PC. If the characters "%P" are in the
installation path itself, a LOAD_INVALID_PARAMETER error is returned to
prevent infinite recursion.
Page 370
The bUninstall argument is ignored unless the tilde (~) character is used to specify the
home key in the key argument. This is to facilitate the anticipated future release of the
Application Manager, which will use the registry values under the home key to
determine user-defined preferences that should be saved if the program is uninstalled.
regValueDelete
The regValueDelete statement deletes a named value from a key in the Windows CE
registry. Most setup applications do not use this statement. The syntax of the command
is as follows:
regValueDelete
key
value
The arguments of the regValueDelete command are detailed in the following list:
key. Specifies the root key that contains the key to receive the integer. This
argument can be the tilde character (~) to specify the "home" key
(HKEY_LOCAL_MACHINE\SOFTWARE\ Apps\your_app_name), or it can be
remoteExec
The remoteExec statement causes Windows CE to begin executing an application on the
target device. The syntax of the command is as follows:
remoteExec
application
[args]
Page 371
The arguments of the remoteExec command are detailed in the following list:
application. Specifies the path and file name of the executable module that
contains the application. The path is relative to the directory specified by the
install directory command-line argument of the Load function. If this argument is
NULL, the module name must be the first space-delimited token in the args
string.
args. Specifies the optional command-line arguments to pass to the application.
TravelManager Installation
The installation process for the TravelManager application is fairly simple because it
has very few files to install. The steps needed in the installation process for
TravelManager are as follows:
1. Create the TravelManager directory (handled in the call to the Load function).
2. Copy the executable file into that directory.
3. Create a shortcut on the desktop for TravelManager.
4. Copy the help files into the Windows directory.
The load script used to perform these actions is as follows:
// copy the files
copy . . trvlmgr.exe
// create a desktop shortcut
createShortcut \Windows\Desktop `Trvlmgr.lnk' . trvlmgr.exe
// copy the help files
copy . \Windows `TravelManager Help.htc'
copy . \Windows trvlmgr1.htp
copy . \Windows trvlmgr2.htp
exit
Page 372
Another area that the installation process could handle is the creation of the registry
keys and values that TravelManager uses. However, the application itself already does
this (so that features developed in earlier chapters did not have to rely on this
installation being performed first). Furthermore, although a Windows CE database for
TravelManager does need to be created, it is accomplished with Windows CE Remote
API functions, which are covered in Chapter 14, "Remote API Functions."
For a real application, the installation of components onto the Handheld PC likely will
be part of a full-fledged installation program that is beyond the scope of this book. To
provide an example of the Application Loader functionality in Windows CE, the
installation example contains a simple executable that merely calls the Application
Loader with a load script file. See Appendix A, "Getting Started with the CD-ROM,"
for information on accessing this code from the accom-panying CD-ROM.
Previous | Table of Contents | Next
CHAPTER 13
File Filters
One of the key features of Windows CE is the capability to transfer data
between the Handheld PC and the desktop PC. The capability to share
information between the desktop computer and the Handheld PC enables the
Windows CE application to be much more than the applications found in
traditional electronic organizers.
Many software applications designed for the Handheld PC are extensions of
applications for the desktop PC. Typically, the Windows CE version of the
application is a slimmed-down companion version of a full-featured
Windows-based desktop application. The Handheld PC version of the
application can be used for remote entry or viewing of data. This data can be
shared and synchronized when the Handheld PC is connected to the desktop
PC.
Windows CE supports multiple forms of desktop connectivity. The previous
chapter presented functionality included with the Windows CE development
environment for installing applications onto the Handheld PC. This chapter
introduces another form of desktop connectivityfunctionality.
Windows CE provides a mechanism for converting data when files are
transferred from the desktop PC to the Handheld PC, or vice versa. The
Handheld PC Explorer uses application-defined file filters to mod-ify data as it
is transferred. Microsoft Word documents, for example, are
Page 375
converted to a slightly different format when they are transferred to the
Handheld PC. Objects and data not supported in Microsoft Pocket Word can
Filter Direction
File filters can be used when transferring files to and from the Handheld PC.
The terms importing and exporting are used to differentiate the direction and
are relative to the Handheld PC. Importing a file involves transferring a file
from the desktop PC to the Handheld PC. Likewise, exporting a file involves
transferring a file from the Handheld PC to the desktop PC.
Page 376
Fortunately, little difference exists between constructing a file filter for
importing or constructing a file filter for exporting.
An application specifies whether a given file filter is used for importing or
exporting through a registry setting. If the value named Import exists under the
PegasusFilters key for the given filter's registry entry, that filter is used for
importing files to the Handheld PC. See the following section for more
information on the registry entries required for defining the file filters.
Registry Entries
The Handheld PC Explorer application on the desktop PC determines which
file filter to use, if any, based on registry settings on the desktop PC. The file
filter entries are queried in the registry based on the file extension of the file
that is transferred with the Handheld PC Explorer. Therefore, it is important
that each file filter is properly registered to be used as files are transferred.
Registering file filters involves adding entries into the Windows registry on the
desktop PC. An extension key is added to define a new filter for a given file
extension and a CLSID key is added to define the specifics of the filter.
Extension Key
One location where information must be set for a file filter is under the
HKEY_LOCAL_MACHINE\SOFWARE\Microsoft\Pegasus\
Filters key. This information defines the extension of the file types that have
available file filters.
Note
Prior to the release of Windows CE, Microsoft used the code
name Pegasus to identify the Windows CE project. The Pegasus
key in the registry was set before the name Windows CE was
chosen and apparently stuckprobably because many
applications were already written to set and use that key.
Page 377
The following listing shows the structure of the information under the
/Filters key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Pegasus\Filters
\.<file extension>
[DefaultImport = <Default import filter CLSID>]
[DefaultExport = <Default export filter CLSID>]
\InstalledFilters
[<CLSID1> = ""]
[<CLSID2> = ""]
. . .
[more CLSID's for this extension]
. . .
[more extensions]
Each key under the HKEY_LOCAL_MACHINE\SOFTWARE\
Microsoft\Pegasus\Filters is the name of a file extension, such as .bmp. These
keys are called extension keys. Every extension key can have a DefaultImport
named value and/or a DefaultExport named value, both of which identify the
default file filter to use when importing or exporting files with the given
extension.
In addition to listing the default file filter for the extension, each extension key
has an InstalledFilters subkey that lists the possible file filters for that file type.
This is because it is certainly possible to have multiple conversion options for
a single file type. For instance, when Word documents are transferred, they
could be converted to Pocket Word documents or to plain ASCII text
documents. An interface in the Handheld PC Explorer application enables the
user to set the conversion used for each file type.
The InstalledFilters keys must contain all possible file filters for that extension
type. Therefore, even file filters specified in the DefaultImport or
Keyword
Brief
Full
Advanced
Search
Search Tips
objects. The CLSID identification is used with file filters because the
filters are implemented as OLE COM objects.
CLSID Key
The other area where file filter information must be defined is under the HKEY_CLASSES_ROOT\CLSID key. This
information defines the specific attributes and implementation details of the file filter. The following listing shows the
structure of the information under the HKEY_CLASSES_ROOT\CLSID key:
HKEY_CLASSES_ROOT\CLSID
\<CLSID>
\(Default) = <Description listed in HPC Explorer>
\DefaultIcon = <filename,index for the icon for this type>
\InProcServer32 = <filename of the DLL that handles his type>
ThreadingModel = "Apartment"
\PegasusFilter
[Import]
[HasOptions]
Description = <String to display in the conversion dialog>
NewExtension = <extension of converted file>
\. . . [more CLSIDs for filters]
Each key under the HKEY_CLASSES_ROOT\CLSID is the class identifier to an object. The CLSID is a series of
hexadecimal numbers separated by dashes, such as DA01ED86-97E8-11CF-8011-00A0C90A8F78. An application
defines its own class identifiers by using the GUID generator application, guidgen.exe. To a very high degree of
certainty, this tool creates a unique CLSIDno other invocation on the same system or any other system should return
the same value.
Under each individual CLSID is a set of values and keys that define the attributes of the object. The value for the
CLSID key itself is the name of the file filter that is listed in the Handheld PC Explorer when it shows the available
conversion filters.
Page 379
The DefaultIcon subkey specifies the location of an icon to be associated with this file filter. The format of the
valuefilename, indexspecifies the name of a file that contains icons, as well as the index for the appropriate icon.
The InProcServer32 subkey identifies the dynamic link library (DLL) that contains the implementation for this file
filter. The value of this key is the name of the file filter plus the extension .dll. This key also has a subkey,
ThreadingModel, whose value defines the Apartment model capabilities of the installed file filter. Generally, this value
is set to "Apartment."
The PegasusFilter subkey defines information specific to file filters. This key can have the following named values:
Import. If this named value exists, the conversion type is used for importing files to the Handheld PC. The
absence of this value means that the conversion type is used for exporting files from the Handheld PC.
HasOptions. If this named value exists, the file filter supports the FilterOptions method of the IpegasusFileFilter
interface.
Description. This named value is a line of text that describes the conversion that the Handheld PC Explorer
displays in the conversion selection dialog box.
NewExtension. This named value is the extension that is used for the destination file name.
"DefaultExport"="Binary Copy"
"DefaultImport"="Binary Copy"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Pegasus\Filters\.wav\InstalledFilters]
Creating a null file filter requires adding the file type key under the ..\Pegasus\Filters key and setting the DefaultImport
and DefaultExport values to "Binary Copy."
When a file with the given extension (.wav in this example) is transferred between the desktop PC and the Handheld
PC, it appears as though a conversion process is taking place (because no warning message is displayed) even though
no filter is being used.
Page 383
Table 13.1
Methods Defined by IPegasusFileFilter, continued
IpegasusFileFilter Method Description
Defined by COM. Increments
AddRef
reference count.
Defined by COM. Decrements
Release
reference count.
Called by the Handheld PC
Explorer to convert a file type
specified in the registry. This
NextConvertFile
method is called repeatedly until the
file filter DLL indicates that the file
conversion is complete.
Called by the Handheld PC
Explorer to display a dialog box that
directs the user to select from
FilterOptions
among the file-filtering options
supported by a file filter. Not
supported in Windows CE version
1.0.
Called by the Handheld PC
FormatMessage
Explorer to format a message string.
Each of these methods is described in the following sections.
QueryInterface, AddRef, Release
These methods are defined by COM. The QueryInterface method allows the
client to dynamically discover at runtime the interfaces supported by the
object. The AddRef and Release methods are used for simple reference
counting.
NextConvertFile
When the user transfers a file for which a file filter is defined, the Hand-held
PC Explorer calls the NextConvertFile method of the appropriate file filter
DLL. Therefore, the NextConvertFile method should be overridden in the file
filter's class derived from IPegasusFileFilter. The NextConvertFile method is
defined as follows:
Page 384
STDMETHOD(NextConvertFile) (THIS_
int nConversion,
PFF_CONVERTINFO* pci,
PFF_SOURCEFILE* psf,
PFF_DESTINATIONFILE* pdf,
volatile BOOL *pbCancel,
PF_ERROR *perr
} PURE;
The parameters of the NextConvertFile method are detailed in the following
list:
int nConversion. This counter is used to convert a single source file into
multiple destination files. This parameter is zero the first time this
function is called and is incremented for each successive call. A simple
filter should return HRESULT_FROM_WIN32
(ERROR_NO_MORE_ITEMS) if this parameter is not zero.
PFF_CONVERTINFO * pci. This parameter points to a
PFF_CONVERTINFO structure that contains information about the
conversion request and a pointer to an IPegasusFileFilterSite object.
PFF_SOURCEFILE * psf. This parameter points to a
PFF_SOURCEFILE structure that contains information about the source
file.
PFF_DESTINATIONFILE * pdf. This parameter points to a
PFF_DESTINATIONFILE structure that contains information about the
destination file.
BOOL * pbCancel. This parameter is a pointer to a BOOL that signals
when the user cancels the conversion process. This variable is updated
asynchronously and can change at any time. The file filter should check
this variable periodically during the file conversion and return
ERROR_CANCELLED if it is ever set to TRUE.
PF_ERROR * perr. This address of a filter-defined error code can be
passed to the IPegasusFileFilter::FormatMessage member function. This
error code will be ignored unless the return value from this function is
E_FAIL.
Page 385
The return value from NextConvertFile should be one of the following values:
FormatMessage
Page 387
searches the system message table if the message is not found in the
module specified by lpSource. This bit flag cannot be used with
FORMAT_MESSAGE_FROM_STRING.
FORMAT_MESSAGE_ARGUMENT_ARRAY. Specifies that the
Arguments parameter is not a va_list structure but instead is just a
pointer to an array of 32-bit values that represent the arguments.
The low-order byte of dwFlags can specify the maximum width of a formatted
output line. The width can be any value between (and including) zero and
FORMAT_MESSAGE_MAX_WIDTH_MASK.
The following is a list of the remaining parameters to the FormatMessage
method:
DWORD dwMessageId. Specifies the 32-bit message identifier for the
requested message. This parameter is ignored if dwFlags includes
FORMAT_MESSAGE_FROM_STRING.
DWORD dwLanguageId. Specifies the 32-bit language identifier for the
requested message. This parameter is ignored if dwFlags includes
FORMAT_MESSAGE_FROM_STRING.
LPSTR lpBuffer. Points to a buffer for the formatted (and
NULL-terminated) message. If dwFlags includes
FORMAT_MESSAGE_ALLOCATE_BUFFER, the function allocates a
buffer by using the LocalAlloc function and places the address of the
buffer at the address specified in lpBuffer.
DWORD nSize. If the FORMAT_MESSAGE_ALLOCATE _BUFFER
flag is not set, this parameter specifies the maximum number of bytes
(ANSI version) or characters (Unicode version) that can be stored in the
output buffer. If FORMAT_MESSAGE _ALLOCATE_BUFFER is set,
Keyword
Brief
Full
Advanced
Search
Search Tips
Page 388
va_list * Arguments. Points to an array of 32-bit values that are used as insert values in the
formatted message: %1 in the format string indicates the first value in the Arguments array, %2
indicates the second argument, and so on.
DWORD * pcb. Points to a DWORD that receives the length of the string returned by the
function. If the FormatMessage function succeeds, pcb holds the number of bytes (ANSI
version) or characters (Unicode version) stored in the output buffer, excluding the terminating
NULL character.
IPegasusFileFilterSite Interface
The other major component used by the file filter is the IPegasusFileFilterSite interface. The
Handheld PC Explorer implements this interface, and a pointer to it is passed to some of the
IPegasusFileFilter methods.
IPegasusFileFilterSite also derives from IUnknown. The methods defined by IPegasusFileFilterSite
include those inherited from the file, as well as methods specific to the file. Table 13.2 describes the
purpose of the methods defined by the IPegasusFileFilterSite interface.
Table 13.2
Methods Defined by IPegasusFileFilterSite
IPegasusFileFilterSite Method Description
Defined by COM. Returns
QueryInterface
pointers to supported interfaces.
Defined by COM. Increments
AddRef
reference count.
Defined by COM. Decrements
Release
reference count.
Called by a file filter to open a
OpenSourceFile
source file.
continues
Page 389
Table 13.2
Methods Defined by IPegasusFileFilterSite, continued
These methods are defined by the Component Object Model. The QueryInterface method allows the
client to dynamically discover at runtime the interfaces supported by the object. The AddRef and
Release methods are used for simple reference counting.
OpenSourceFile
This member function is used by a file filter to open a source file. The OpenSourceFile method is
defined as follows:
STDMETHOD(OpenSourceFile) (THIS_
int nHowToOpenFile,
LPVOID *ppObj
) PURE;
The parameters to OpenSourceFile are detailed in the following list:
int nHowToOpenFile. Specifies how the source file is to be opened. Currently, the only
supported value is PF_OPENFLAT, which opens the file as a flat file.
Page 390
LPVOID ppObj. Specifies the address of an LPVOID variable that will receive an IStream
pointer.
OpenDestinationFile
This member function is used by a file filter to open a destination file. The OpenDestinationFile
method is defined as follows:
STDMETHOD(OpenDestinationFile) (THIS_
int nHowToOpenFile,
LPCSTR pszFullpath,
LPVOID *ppObj
) PURE;
The parameters to OpenDestinationFile are detailed in the following list:
int nHowToOpenFile. Specifies how the source file is to be opened. Currently, the only
supported value is PF_OPENFLAT, which opens the file as a flat file.
LPCSTR pszFullpath. Specifies the file name to open to override the default destination file
name. If this parameter is NULL, the default destination file name is used.
LPVOID ppObj. Specifies the address of an LPVOID variable that will receive an Istream
pointer.
CloseSourceFile
This member function is used by a file filter to close a source file. This function is defined as follows:
STDMETHOD(CloseSourceFile) (THIS_
LPUNKNOWN pObj
) PURE;
The parameter to CloseSourceFile is LPUNKNOWN pObj, which points to the IStream object
returned from the IPegasusFileFilterSite ::OpenSourceFile method.
Page 391
CloseDestinationFile
This member function is used by a file filter to close a destination file. The function is defined as
follows:
STDMETHOD(CloseDestinationFile) (THIS_
BOOL bKeepFile,
LPUNKNOWN pObj
) PURE;
The parameters to CloseDestinationFile are detailed in the following list:
BOOL bKeepFile. Indicates whether to keep or delete the destination file. A file filter should
set this parameter to TRUE to keep the destination file, or FALSE to delete it.
LPUNKNOWN pObj. Points to the IStream object returned from the
IPegasusFileFilterSite::OpenDestinationFile method.
ReportProgress
This member function is used by a file filter to report the progress of a file conversion. The function
is defined as follows:
STDMETHOD(ReportProgress) (THIS_
UINT nPercent
) PURE;
The parameter to ReportProgress is UINT nPercent, which specifies the completed percentage of the
operation. If, for example, the file filter has converted 25 percent of a file, this parameter should be
set to 25.
ReportLoss
The ReportLoss member function is used by a file filter to report any information that it intentionally
discarded during a file conversion. The file filter specifies a message that explains the data loss, and
Handheld PC Explorer formats and displays the message in a message box when the file conversion
is completed. The file filter can specify either the identifier of a message table resource or the address
of a buffer that contains the message string.
Page 392
The ReportLoss method is defined as follows:
STDMETHOD(ReportLoss) (THIS_
DWORD dw,
LPCTSTR psz,
va_list args
) PURE;
The parameters to ReportLoss are detailed in the following list:
DWORD dw. Specifies a 32-bit message identifier. The member function uses
IPegasusFileFilter::FormatMessage to format the message. If the format fails (for example, the
message identifier could not be recognized), then the system function FormatMessage is used.
LPCTSTR psz. Points to the message string to display. This parameter should be NULL if the
dw parameter is used.
va_list args. Points to an array of 32-bit values that are used as insert values in the formatted
message. %1 in the format string indicates the first value in the Arguments array, %2 indicates
the second argument, and so on.
Page 393
HWND hwndParent. Specifies the handle of the window that a file filter can use as the parent window for a dialog
box.
BOOL bYesToAll. Points to a flag that determines whether the Yes to All button is included in the Overwrite File?
dialog box. This dialog box asks the user to verify that the destination file(s) should be overwritten. If there is more
than one subconversion, the filter should set this member to TRUE to include the Yes to All button; otherwise, the
filter should set this member to FALSE.
IPegasusFileFilterSite * pffs. Points to an IPegasusFileFilterSite interface used for opening and closing files.
The PFF_DESTINATIONFILE structure contains information about a destination file. A pointer to this structure is passed
in the call to the IPegasusFileFilter::NextConvertFile method. The members of this structure are detailed in the following
list:
TCHAR szFullpath. Specifies the default full path of the destination file.
TCHAR szPath. Specifies the path of the directory where the destination file should be created.
TCHAR szFilename. Specifies only the base name (no extension) of the destination file.
TCHAR szExtension. Specifies the file name extension of the destination file.
The PFF_SOURCEFILE structure contains information about a source file. A pointer to this structure is passed in the call to
the IPegasusFileFilter::NextConvertFile method. The members of this structure are detailed in the following list:
TCHAR szFullpath. Specifies the fully qualified path of the source file.
TCHAR szPath. Specifies the path of the directory containing the source file.
Page 394
TCHAR szFilename. Specifies only the base name (no extension) of the source file.
TCHAR szExtension. Specifies the file name extension of the source file.
DWORD cbSize. Specifies the size of the source file.
FILETIME ftCreated. Specifies a FILETIME structure that indicates the time when the source file was created.
FILETIME ftModified. Specifies a FILETIME structure that indicates the time when the file was last modified.
File Filter Process
The sequence of steps involved in file-conversion process with a file filter is defined and straightforward. The steps of the
conversion process can be summarized as follows:
1. When requested to copy a file, the Handheld PC Explorer queries the registry for information on any file filter
defined for that file type.
2. If a file filter is defined for that file type, the Handheld PC Explorer loads the specified filter DLL.
3. The Handheld PC Explorer calls the file filter's IPegasusFileFilter ::NextConvertFile method to perform the custom
file conversion. The PFF_CONVERTINFO, PFF_DESTINATIONFILE, and PFF_SOURCEFILE structures are
passed as parameters to provide information.
4. Inside the NextConvertFile method, the file filter begins the file conversion.
5. The source file is opened by using the IPegasusFileFilterSite ::OpenSourceFile method.
6. The destination file is opened by using the IPegasusFileFilterSite ::OpenDestinationFile method.
Page 395
7. Data is read from the open source stream, converted, and written out to the open destination stream.
8. During the read-convert-write process, the file filter should call the IPegasusFileFilterSite::ReportProgress method to
update a graphical display that shows the progress of the file conversion.
9. If the file filter DLL intentionally discards any of the file data, the filter can call the
IPegasusFileFilterSite::ReportLoss method so that the Handheld PC Explorer can display a message when the file
conversion is complete. This method can in turn call the filter's IPegasusFileFilter::FormatMessage method to
properly format the message.
10. Steps 7-9 are repeated until all the data from the source file is read.
11. The source file is closed with the IPegasusFileFilterSite ::CloseSourceFile method.
12. The destination file is closed with the IPegasusFileFilterSite
::CloseDestinationFile method.
File Filter Example
The functionality of the TravelManager application does not require a specific file format, so no file filter is needed.
However, to illustrate the file filter technique, a sample file filter has been created.
This sample file filter handles files on the desktop PC with the extension .lwr. When transferred to the Handheld PC, all
characters in a .lwr file are converted to uppercase and are given the extension .upr.
The first step in defining a file filter is adding the proper entries to the registry on the desktop PC. An importable .reg file
that configures the registry for the .lwr file is listed in the following code:
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Pegasus\Filters\.lwr]
Page 396
"DefaultImport"="{71eaa5b0-e920-11d0-9a30-204c4f4f5020}"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Pegasus\Filters\.lwr\InstalledFilters]
"{71eaa5b0-e920-11d0-9a30-204c4f4f5020}"=""
[HKEY_CLASSES_ROOT\CLSID\{71eaa5b0-e920-11d0-9a30-204c4f4f5020}]
@="File Filter Sample"
[HKEY_CLASSES_ROOT\CLSID\{71eaa5b0-e920-11d0-9a30-204c4f4f5020}\DefaultIcon]
@="filter.dll,-102"
[HKEY_CLASSES_ROOT\CLSID\{71eaa5b0-e920-11d0-9a30-204c4f4f5020}\InProcServer32]
@="e:\\wce\\code\\chap13\\release\\filter.dll"
"ThreadingModel"="Apartment"
[HKEY_CLASSES_ROOT\CLSID\{71eaa5b0-e920-11d0-9a30-204c4f4f5020}\PegasusFilter]
"Import"=""
"Description"="FILTER: Copy a .lwr file converting to all uppercase."
"NewExtension"="upr"
[HKEY_CLASSES_ROOT\.lwr]
@="lwrfile"
[HKEY_CLASSES_ROOT\lwrfile]
@="FILTER: Lowercase File"
[HKEY_CLASSES_ROOT\lwrfile\DefaultIcon]
@="e:\\wce\\code\\chap13\\release\\filter.dll,-102"
[HKEY_CLASSES_ROOT\.upr]
@="uprfile"
[HKEY_CLASSES_ROOT\uprfile]
@="FILTER: Uppercase File"
[HKEY_CLASSES_ROOT\uprfile\DefaultIcon]
@="e:\\wce\\code\\chap13\\release\\filter.dll,-103"
After the registry is configured, the remaining step is to create the fil-ter.dll that is used when a file of type .lwr is
transferred to the
Page 397
Handheld PC. In the interest of space, all the code required to create the filter.dll is not listed here. The companion
CD-ROM contains the complete set of source code for the file filter. See Appendix A, "Getting Started with the CD-ROM,"
for information on accessing the code from the CD-ROM.
The most interesting part of the file filter source code is the ConvertFile function. This function performs the actual reading,
converting, and writing of the file being transferred. If this file filter sample is used to create another file filter, this function
is what must be changed to perform the proper conversion.
The ConvertFile function simply reads in a part of the file from the input stream, performs the conversion to lowercase, and
writes the file back to the destination stream. ConvertFile continues this process until the entire file has been processed or it
is signaled that the user has canceled the operation. The ConvertFile function is listed in the following code:
STDMETHODIMP ConvertFile (
IStream *pstmSrc,
IStream *pstmDst,
IPegasusFileFilterSite *pffs,
PFF_SOURCEFILE *psf,
volatile BOOL *pbCancel,
PF_ERROR *perr
)
{
// Generic error code
*perr = ERROR_ACCESS_DENIED;
//
//
//
//
//
//
HRESULT hres;
DWORD cb;
DWORD cbProcessed = 0;
BYTE buf[2048];
for ( ; ; )
{
Previous | Table of Contents | Next
CHAPTER 14
values as the corresponding Windows CE versions. This also means that the
RAPI functions expect strings in Unicode format, which means that if the
desktop application is non-Unicode, it must use the appropriate conversion
routines.
Using RAPI Functions
Although an application on the desktop PC can use the Windows CE remote
API functions just like other Win32 API functions, the system first must be
initialized. An application calls the PegRapiInit or Peg-RapiInitEx function to
perform routine initialization and set up the communications link between the
PC and the device. The only difference is that PegRapiInit is a synchronous
operation, while PegRapiInitEx is not.
When an application is finished using the remote API functions, the
PegRapiUninit function should be called to terminate the connection and
perform any necessary cleanup. Creating and terminating connections are
fairly expensive operations; whenever possible, an application should establish
and terminate the link only once per session, not on a per-call basis.
Page 402
PegRapiInit
Description
Returns the last RAPI error value.
Returns the calling thread's last-error value;
PegGetLastError quivalent to calling GetLastError on the
device.
Initializes the Windows CE Remote API
PegRapiInit
asynchronously.
Attempts to initialize the Windows CE
PegRapiInitEx
Remote API asynchronously.
PegRapiUninit Uninitializes the Windows CE Remote API.
Frees the memory on the desktop PC
RapiFreeBuffer allocated by a call to PegFindAllDatabase,
PegFindAllFiles,or PegReadRecordProps.
Each of these functions is discussed in the following sections.
GetRapiError
The GetRapiError function can be used to determine whether a call failed due
to an internal failure within the Remote API. GetRapiError is a host-side RAPI
function. The syntax of the function is as follows:
HRESULT GetRapiError(void);
The return value is the last RAPI error-code value.
Previous | Table of Contents | Next
PegGetLastError
The function PegGetLastError returns the calling thread's last error code. This is the RAPI version of the
function GetLastError. The syntax of the function is as follows:
DWORD PegGetLastError(void);
The return value is the calling thread's last error code.
PegRapiInit
Syntax for this function is listed in the "Using RAPI Functions," section later in this chapter.
PegRapiInitEx
Syntax for this function is listed in the "Using RAPI Functions," section later in this chapter.
PegRapiUninit
Syntax for this function is listed in the "Using RAPI Functions," section later in this chapter.
RapiFreeBuffer
Description
Closes an open object handle.
PegCopyFile
PegCreateDirectory
The PegFindAllFiles function retrieves information about all files and directories in the given directory of
the Windows CE object store. The function copies information to an array of PEG_FIND_DATA structures.
The syntax of the function is as follows:
BOOL PegFindAllFiles(
LPCWSTR szPath,
DWORD dwFlags,
LPDWORD lpdwFoundCount,
LPLPPEG_FIND_DATA ppFindDataArray
);
The parameters to PegFindAllFiles are defined in the following list:
LPCWSTR szPath. Pointer to the name of the path in which to search for files.
DWORD dwFlags. A combination of filter and retrieval flags. The filter flags specify what kinds of
files to document, and the retrieval flags specify which members of the structure PEG_FIND_DATA
to retrieve. The filter and retrieval flags can be a combination of the values in Table 14.3.
Page 408
LPDWORD lpdwFoundCount. Pointer to a variable that receives a count of the items found.
LPLPPEG_FIND_DATA ppFindDataArray. Pointer to the address of an array of PEG_FIND_DATA
structures that receive information about the found items. It is the application's responsibility to free
the memory used by the array. To free the memory, you must call RapiFreeBuffer.
Table 14.3
Filter and Retrieval Flags
Filter or Retrieval Flag
Description
Does not retrieve information for files
FAF_ATTRIB_NO_HIDDEN
or directories that have the hidden
attribute set.
Only retrieves information for
FAF_FOLDERS_ONLY
directories.
Does not retrieve information for files
FAF_NO_HIDDEN_SYS_ROMMODULES or directories that have the hidden,
system, or inrom attributes set.
Retrieves the
FILE_ATTRIBUTE_HAS_CHILDREN
FAF_ATTRIB_CHILDREN
file attribute and copies it to the
dwFileAttributes member.
Retrieves the file attributes and copies
FAF_ATTRIBUTES
them to the dwFileAttributes member.
Retrieves the file creation time and
FAF_CREATION_TIME
copies it to the ftCreationTime member.
continues
Page 409
Table 14.3
Filter and Retrieval Flags, continued
Filter or Retrieval Flag
Description
Retrieves the time the file was
FAF_LASTACCESS_TIME last accessed and copies it to the
ftLastAccessTime member.
Retrieves the time the file was
FAF_LASTWRITE_TIME last written to and copies it to the
ftLastWriteTime member.
Retrieves the high-order
DWORD value of the file size
FAF_SIZE_HIGH
and copies it to the nFileSizeHigh
member.
FAF_SIZE_LOW
FAF_OID
FAF_NAME
PegGetStoreInformation
The PegGetStoreInformation function fills in a STORE_ INFORMATION structure with the size of the
object store and the amount of free space currently in the object store. This is the RAPI version of
GetStoreInformation. The syntax of the function is as follows:
BOOL PegGetStoreInformation( LPSTORE_INFORMATION lpsi );
PAGE 410
The lpsi parameter is a pointer to a STORE_INFORMATION structure to be filled by this function. The
STORE_INFORMATION structure has two DWORD membersdwStoreSize and dwFreeSizethat
specify the size (in bytes) of the object store and the amount of free space (in bytes) in the object store,
respectively.
Database Functions
Table 14.4 lists the RAPI functions used to manipulate Windows CE database from an application running
on the desktop PC.
Table 14.4
RAPI Database Functions
Function
PegCreateDatabase
Description
Creates a new database.
Removes a database from the object
PegDeleteDatabase
store.
PegDeleteRecord
Deletes a record from a database.
Retrieves information about all
PegFindAllDatabases databases of a given type residing on the
device.
Opens an enumeration context for all
PegFindFirstDatabase
databases in the system.
Retrieves the next database in an
PegFindNextDatabase
enumeration context.
PegOpenDatabase
Opens an existing database.
Reads properties from the current
PegReadRecordProps
record.
PegSeekDatabase
Seeks a record in an open database.
PegSetDatabaseInfo Sets various database parameters.
Writes a set of properties to a single
PegWriteRecordProps
record.
Previous | Table of Contents | Next
Most of the remote database functions are identical in syntax to the Windows CE database functions, with
the exception of the PegFindAllDatabases function.
PegFindAllDatabases
The PegFindAllDatabases function is a RAPI function that retrieves information about all databases of a
given type that reside on the Handheld PC. This function copies information to an array of
PEGDB_FIND_DATA structures. The syntax of the function is as follows:
BOOL PegFindAllDatabases(
DWORD dwDbaseType,
WORD wFlags,
LPWORD cFindData,
LPLPPEGDB_FIND_DATA ppFindData
);
The parameters to PegFindAllDatabases are detailed in the following list:
DWORD dwDbaseType. Type identifier of the databases to seek.
WORD wFlags. Members of the PEGDB_FIND_DATA structure that are to be retrieved. This
parameter can be a combination of the following values:
FAD_OID. Retrieves the OidDb member.
FAD_FLAGS. Retrieves the DbInfo.dwFlags member.
FAD_NAME. Retrieves the DbInfo.szDbaseName member.
FAD_TYPE. Retrieves the DbInfo.dwDbaseType member.
FAD_NUM_RECORDS. Retrieves the DbInfo.dwNumRecords member.
FAD_NUM_SORT_ORDER. Retrieves the DbInfo.dwNumSortOrder member.
Page 412
FAD_SORT_SPECS. Retrieves the DbInfo.rgSortSpecs member.
LPWORD cFindData. Pointer to a variable that receives a count of the items found.
LPLPPEGDB_FIND_DATA ppFindData. Pointer to the address of an array of PEGDB_FIND_DATA
structures that receives information about the found items. It is the application's responsibility to free
the memory used by the array. To free the memory, the application must call RapiFreeBuffer.
The members of the PEGDB_FIND_DATA are detailed in the following list:
PEGOID OidDb. Specifies the object identifier of a database in the Windows CE object store.
PEGDBASEINFO DbInfo. Specifies a PEGDBASEINFO structure that contains information about a
database.
Registry Functions
Table 14.5 lists the RAPI functions that are used to access the Windows CE registry on the Handheld PC.
Table 14.5
RAPI Registry Functions
Function
PegRegCloseKey
PegRegCreateKeyEx
PegRegDeleteKey
PegRegDeleteValue
PegRegEnumKeyEx
PegRegEnumValue
Description
Releases a key handle.
Creates a key.
Deletes a key and all its descendants.
Deletes a value from a key.
Enumerates the subkeys of an open key.
Enumerates the values of an open key.
continues
Page 413
Table 14.5
RAPI Registry Functions, continued
Function
Description
PegRegOpenKeyEx Opens a key.
PegRegQueryInfoKey Retrieves information about a key.
Retrieves the type and data for a value
PegRegQueryValueEx
name associated with an open key.
Stores data in the value field of an open
PegRegSetValueEx
key.
All the remote registry functions have the same syntax as the Windows CE Registry functions, which are
described in Chapter 9, "Registry and File System."
Window Management Functions
The RAPI functions used to perform simple window management are listed in Table 14.6.
Table 14.6
RAPI Window Management Functions
Function
Description
PegGetClassName Retrieves the name of a window's class.
PegGetWindow
Retrieves a window handle.
PegGetWindowLong Retrieves information about a window.
Gets the text of a window's title bar, if it
PegGetWindowText
has one.
System Functions
Table 14.7 lists the RAPI functions that grant system access to the Windows CE device.
Page 414
Table 14.7
RAPI System Access Functions
Function
PegCheckPassword
Description
Compares a string to the system
password.
The PegCheckPassword function compares a specified string to the system password. This function is the
RAPI version of the Windows CE CheckPassword function. The syntax of the function is as follows:
BOOL PegCheckPassword( LPWSTR lpszPassword );
The lpszPassword parameter is a pointer to a wide character string to compare with the system password.
The function returns TRUE if lpszPassword matches the system password or FALSE if it doesn't match.
Page 415
PegGetDesktopDeviceCaps
The PegGetDesktopDeviceCaps function retrieves device-specific information about a specified device. This
is the remote API version of the GetDeviceCaps function. The syntax of the function is as follows:
INT PegGetDesktopDeviceCaps( INT nIndex );
The nIndex parameter specifies the information to return. This parameter can be one of the following values
listed in Table 14.8.
Table 14.8
PegGetDesktopDeviceCaps Information
Function
Description
DRIVERVERSION The device driver version.
Device technology. The return value could
TECHNOLOGY be DT_PLOTTER, DT_RASDISPLAY,
or DT_RASPRINTER.
Width, in millimeters, of the physical
HORZSIZE
screen.
Height, in millimeters, of the physical
VERTSIZE
screen.
HORZRES
VERTRES
LOGPIXELSX
LOGPIXELSY
BITSPIXEL
PLANES
NUMBRUSHES
NUMPENS
NUMFONTS
NUMCOLORS
Page 416
Function
ASPECTX
ASPECTY
ASPECTXY
CLIPCAPS
SIZEPALETTE
NUMRESERVED
COLORRES
RASTERCAPS
CURVECAPS
LINECAPS
Description
Relative width of a device pixel used for
line drawing.
Relative height of a device pixel used for
line drawing.
Diagonal width of the device pixel used
for line drawing.
Flag that indicates the clipping
capabilities of the device. If the device
can clip to a rectangle, it is 1. Otherwise,
it is 0.
Number of entries in the system palette.
This index is valid only if the device
driver sets the RC_PALETTE bit in the
RASTERCAPS.
Number of reserved entries in the system
palette. This index is valid only if the
device driver sets the RC_PALETTE bit
in the RASTERCAPS index and is
available only if the driver is compatible
with Windows version 3.0 or later.
Actual color resolution of the device, in
bits per pixel. This index is valid only if
the device driver sets the RC_PALETTE
bit in the RASTERCAPS index and is
available only if the driver is compatible
with Windows version 3.0 or later.
Value that indicates the raster
capabilities of the device. The return
value is RC_BITBLT, RC_PALETTE,
or RC_STRETCHBLT.
Value that indicates the curve
capabilities of the device.
Value that indicates the line capabilities
of the device. The return value is
LC_POLYLINE, LC_WIDE, or
LC_STYLED.
PegGetSystemInfo
The PegGetSystemInfo function returns information about the current system. This is the RAPI version of
the GetSystemInfo function. The syntax of the function is as follows:
void PegGetSystemInfo( LPSYSTEM_INFO lpSystemInfo );
The lpSystemInfo parameter is a pointer to a SYSTEM_INFO structure to be filled in by this function. The
SYSTEM_INFO structure has the following members:
DWORD dwOemId. Always set to zero.
DWORD dwPageSize. Returns the page size and specifies the granularity of page protection and
commitment.
LPVOID lpMinimumApplicationAddress. Returns the lowest memory address accessible to
applications and dynamic-link libraries (DLLs).
LPVOID lpMaximumApplicationAddress. Returns the highest memory address accessible to
applications and DLLs.
DWORD dwActiveProcessorMask. Returns a mask representing the set of processors configured
into the system. Bit zero is processor zero; bit 31 is processor 31.
DWORD dwNumberOfProcessors. Returns the number of processors in the system.
DWORD dwProcessorType. Returns the processor type, which can be one of the following values:
PROCESSOR_INTEL_386
PROCESSOR_INTEL_486
PROCESSOR_INTEL_PENTIUM
PROCESSOR_MIPS_R2000
PROCESSOR_MIPS_R3000
Page 418
PROCESSOR_MIPS_R4000
PROCESSOR_HITACHI_SH3
PROCESSOR_ALPHA_21064
DWORD dwAllocationGranularity. Returns the allocation granularity in which memory will be
allocated. This value was hard-coded as 64K in the past, but other hardware architectures might
require different values.
PegGetSystemPowerStatusEx
The PegGetSystemPowerStatusEx function retrieves the power status of the system. This status indicates
whether the system is running on AC or DC power and whether or not the batteries are currently charging.
The power status also returns the remaining life of main and backup batteries. The
PegGetSystemPowerStatusEx function is the RAPI version of the GetSystemPowerStatusEx function. The
syntax of the function is as follows:
BOOL PegGetSystemPowerStatusEx(
PSYSTEM_POWER_STATUS_EX pstatus,
BOOL fUpdate
);
The fUpdate parameter specifies where to get the requested
power information. If this parameter is set to TRUE,
PegGetSystemPowerStatusEx gets the latest information from the
device driver. Otherwise, the function retrieves cached information
that could be out of date by several seconds.
The pstatus parameter is a pointer to the SYSTEM_POWER_
STATUS_EX structure receiving the power status information. This structure has the following members:
BYTE ACLineStatus. AC power status. This parameter can be a value of 0 for offline, 1 for online,
or 255 for unknown status.
Page 419
BYTE BatteryFlag. Battery charge status. This parameter can be a value of 1 for high, 2 for low, 4
for critical, 8 for charging, 128 for no system battery, or 255 for unknown status.
BYTE BatteryLifePercent. Percentage of full battery charge remaining. This member can be a value
in the range 0 to 100, or 255 if status is unknown. All other values are reserved.
DWORD BatteryLifeTime. Number of seconds of battery life remaining, or 0xFFFFFFFF if
remaining seconds are unknown.
DWORD BatteryFullLifeTime. Number of seconds of battery life when at full charge, or
0xFFFFFFFF if full lifetime is unknown.
BYTE BackupBatteryFlag. Backup battery charge status, which must be one of the following:
BATTERY_FLAG_HIGH
BATTERY_FLAG_CRITICAL
BATTERY_FLAG_CHARGING
BATTERY_FLAG_NO_BATTERY
BATTERY_FLAG_UNKNOWN
BATTERY_FLAG_LOW
BYTE BackupBatteryLifePercent. Percentage of full backup battery charge remaining. Must be in
the range 0 to 100, or BATTERY_PERCENTAGE_UNKNOWN.
DWORD BackupBatteryLifeTime. Number of seconds of backup battery life remaining, or
BATTERY_LIFE_UNKNOWN if remaining seconds are unknown.
DWORD BackupBatteryFullLifeTime. Number of seconds of backup battery life when at full
charge, or BATTERY_LIFE_UNKNOWN if full lifetime is unknown.
Page 420
PegSHCreateShortcut
The PegSHCreateShortcut function creates a shortcut. This is the RAPI version of the SHCreateShortcut
The PegSHGetShortcutTarget function retrieves the path to which the shortcut points. This is the RAPI
version of the SHGetShortcutTarget function. The syntax of the function is as follows:
BOOL PegSHGetShortcutTarget(
LPWSTR lpszShortcut,
LPWSTR lpszTarget,
int cbMax
);
The parameters to the PegSHGetShortcutTarget function are detailed in the following list:
LPWSTR szShortcut. Pointer to a buffer that contains the name of the shortcut to retrieve.
LPWSTR szTarget. Pointer to a buffer that gets the target path of the shortcut.
int cbMax. Maximum number of characters to copy (size of szTarget buffer).
Page 421
RAPI Example
An example of the Windows CE Remote API functionality can be seen in the example program used to
create and populate the TravelManager's Windows CE database. This RAPI application creates the data for
TravelManager that was retrieved and displayed with the changes from Chapter 10, "Windows CE
Databases."
The RAPI example performs the following steps:
1. Initializes the RAPI connection.
2. Creates the TravelManager database with the CreateDatabase function.
3. Inserts some records into the database with the InsertData function.
4. Disconnects from the device.
The source code for this RAPI example follows and also can be found on the companion CD-ROM. See
Appendix A, "Getting Started with the CD-ROM," for information on using the CD-ROM.
//-------------------------------------------------------//
// Sample application from Windows CE Programming
//
// Description: This console application uses RAPI to
//
create a Windows CE database on the H/PC
//
and insert some records into the
//
database.
//
//--------------------------------------------------------
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <rapi.h>
Page 422
// Function prototypes
PEGOID CreateDatabase();
BOOL InsertData(PEGOID PegOid);
int main( int argc, char *argv[])
{
HRESULT hRapiResult;
PEGOID PegOid;
tprintf(TEXT("Initializing RAPI Connection..."));
hRapiResult = PegRapiInit();
if (FAILED(hRapiResult))
{
tprintf(TEXT("FAILED.\n"));
return _1;
}
else
{
tprintf(TEXT("Success.\n"));
}
tprintf(TEXT("Creating TravelManager database..."));
if ((PegOid = CreateDatabase()) == (PEGOID)NULL)
{
tprintf(TEXT("FAILED.\n"));
return _1;
}
else
{
tprintf(TEXT("Success.\n"));
}
tprintf(TEXT("Inserting records..."));
if (InsertData(PegOid) == FALSE)
{
tprintf(TEXT("FAILED.\n"));
return _1;
}
else
Page 423
{
tprintf(TEXT("Success.\n"));
}
_tprintf(TEXT("Disconnecting from device.\n"));
PegRapiUninit();
_tprintf(TEXT("Database installation complete..\n"));
}
PEGOID CreateDatabase()
{
PEGOID PegOid;
TCHAR szDBName[PEGDB_MAXDBASENAMELEN];
DWORD dwDBType;
SORTORDERSPEC sortorders[1];
tcscpy(szDBName, TEXT("TravelManager Database"));
dwDBType = 123456;
sortorders[0].propid = MAKELONG( PEGVT_FILETIME, 0);
PegOid = PegCreateDatabase(szDBName, dwDBType, 1, sortorders);
if (PegOid == (PEGOID)NULL)
{
// Could get extended error info with PegGetLastError
return (PEGOID)NULL;
}
return PegOid;
}
BOOL InsertData(PEGOID PegOid)
{
HANDLE
hDB;
PEGPROPVAL Properties[7];
FILETIME
FileTime;
SYSTEMTIME SystemTime;
LPVOID
lpStr1, lpStr2, lpStr3;
PEGOID pegoidRecord;
Previous | Table of Contents | Next
Keyword
Brief
Full
Advanced
Search
Search Tips
Properties[2].wFlags = 0;
Properties[2].val.lpwstr = lpStr1;
//To - LPWSTR type
lpStr2 = LocalAlloc(LMEM_FIXED, 50 * sizeof(TCHAR));
tcscpy(lpStr2, TEXT("Seattle"));
Page 425
Properties[6].wFlags = 0;
Properties[6].val.lpwstr = lpStr3;
if (!PegWriteRecordProps(hDB, 0, 7, Properties))
{
if( lpStr1 )
LocalFree(lpStr1);
if( lpStr2 )
LocalFree(lpStr2);
if( lpStr3 )
LocalFree(lpStr3);
CloseHandle(hDB);
return FALSE;
}
// Insert record #2
//Date - FILETIME type
SystemTime.wYear = 1997;
SystemTime.wMonth = 6;
SystemTime.wDayOfWeek = 6;
SystemTime.wDay = 21;
SystemTime.wHour = 0;
SystemTime.wMinute = 0;
SystemTime.wSecond = 0;
SystemTime.wMilliseconds = 0;
SystemTimeToFileTime(&SystemTime,&FileTime);
Properties[0].propid = MAKELONG( PEGVT_FILETIME, 0);
Properties[0].wLenData = 0;
Properties[0].wFlags = 0;
Properties[0].val.filetime = FileTime;
//Flight - USHORT type
Properties[1].propid = MAKELONG( PEGVT_UI2, 1);
Properties[1].wLenData = 0;
Properties[1].wFlags = 0;
Properties[1].val.uiVal = 682;
//From - LPWSTR type
_tcscpy(lpStr1, TEXT("Seattle"));
Page 427
_tcscpy(lpStr2, TEXT("Indianapolis"));
Properties[3].propid = MAKELONG(PEGVT_LPWSTR, 3);
Properties[3].wLenData = 0;
Properties[3].wFlags = 0;
Properties[3].val.lpwstr = lpStr2;
//Departs - FILETIME type
SystemTime.wYear = 1997;
SystemTime.wMonth = 6;
SystemTime.wDayOfWeek = 6;
SystemTime.wDay = 21;
SystemTime.wHour = 14;
SystemTime.wMinute = 5;
SystemTime.wSecond = 0;
SystemTime.wMilliseconds = 0;
SystemTimeToFileTime(&SystemTime,&FileTime);
Properties[4].propid = MAKELONG( PEGVT_FILETIME, 4);
Properties[4].wLenData = 0;
Properties[4].wFlags = 0;
Properties[4].val.filetime = FileTime;
//Arrives - FILETIME type
SystemTime.wYear = 1997;
SystemTime.wMonth = 6;
SystemTime.wDayOfWeek = 6;
SystemTime.wDay = 21;
SystemTime.wHour = 21;
SystemTime.wMinute = 50;
SystemTime.wSecond = 0;
SystemTime.wMilliseconds = 0;
SystemTimeToFileTime(&SystemTime,&FileTime);
Properties[5].propid = MAKELONG( PEGVT_FILETIME, 5);
Properties[5].wLenData = 0;
Properties[5].wFlags = 0;
Page 428
Properties[5].val.filetime = FileTime;
//Seat - LPWSTR type
_tcscpy(lpStr3, TEXT("8D"));
Properties[6].propid = MAKELONG(PEGVT_LPWSTR, 6);
Properties[6].wLenData = 0;
Properties[6].wFlags = 0;
Properties[6].val.lpwstr = lpStr3;
pegoidRecord = PegWriteRecordProps(hDB, 0, 7, Properties);
if( lpStr1 )
LocalFree(lpStr1);
if( lpStr2 )
LocalFree(lpStr2);
if( lpStr3 )
LocalFree(lpStr3);
CloseHandle(hDB);
if (pegoidRecord == 0)
{
return FALSE;
}
else
{
return TRUE;
}
}
Page 429
Previous | Table of Contents | Next
Appendix A
Installation
The source code for each chapter is organized in a Visual C++ 5.0 project
workspace. Each project has been built for all the supported project
configurationsthe proper executable can be copied directly to the emulation
environment or Windows CE device.
If you would like to modify or extend a particular project, follow these steps:
1. Create a directory on your PC, for instance:
c:\wceprog\trvlmgr
2. Copy the contents of the desired directory from the CD-ROM to the
directory on the PC:
copy f:\trvlmgr\*.* c:\wceprog\trvlmgr
3. Open the project workspace file from the new directory in Visual C++
5.0.
4. Modify and rebuild the project as desired.
Technical Support
If you cannot get the CD to install properly or you need assistance with a
particular situation in the book, please feel free to check out the Knowledge
Base on our Web site at http://www.superlibrary.com/general/support. We
have answers to our most Frequently Asked Questions listed there. If you do
not find your specific question answered, please contact Macmillan Technical
Support at 317-581-3833. We can also be reached by e-mail at
[email protected].
Previous | Table of Contents |