You are on page 1of 101

Connexions module: m14425 1

VC++ Tutorial for Beginners ∗

Avanija j
This work is produced by The Connexions Project and licensed under the
Creative Commons Attribution License †

Abstract
This course entails the programming concepts in VC++ with clear syntax specication and program-
ming examples.

1 Chapter 1
2 Basics of Windows Programming
3 1. 1 Paradigms of Programming Languages
Although many dierent computer architectures are being developed, the most prevalent is still the tradi-
tional von Neumann architecture - consisting of a single sequential CPU separate from memory, with data
piped between cpu and memory. This is reected in the design of the dominant computer languages, with
dynamic variables (representing memory cells with changing values); sequential iteration (reecting the sin-
gle sequential cpu); assignment statements (reecting piping). This combination of choices gives rise to the
imperative language paradigm - C, Ada, Pascal, FORTRAN, COBOL, Basic etc.
But other choices are possible - variables do not have to directly reect memory cells (logic programming);
repetition need not be iterative (logic, functional, concurrent); assignment need not be important (logic,
functional); data and control need not be separated (object oriented, functional).
A paradigm is essentially a high level model of what computation is about - the unifying factor that
makes Ada and C seem very similar, ignoring details such as what data or control structures are available,
exactly how variables are passed to procedures, and so on.

3.1 Some Paradigms


• Procedural (COBOL, FORTRAN, Pascal, C)
• functional (LISP)
• logic (PROLOG)
• structured
• object-oriented (Smalltalk)
• 4GL (Dbase)
• Visual (Visual Basic)

1.1.1 Procedural
∗ Version 1.1: Apr 4, 2007 12:57 pm GMT-5
† http://creativecommons.org/licenses/by/2.0/

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 2

This is focusing on grouping organizations and/or code by similar operations or by the operations that
can be done on them.
1.1.2 Functional
Functional programming is so called because a program consists entirely of functions. The program itself
is written as a function which receives the program's input as its argument and delivers the program's output
as its result. Typically the main function is dened in terms of other functions, which in turn are dened in
terms of still more functions, until at the bottom level the functions are language primitives. These functions
are much like ordinary mathematical functions.
Functional programs contain no assignment statements, so variables, once given a value, never change.
Functions can be described intentionally by a rule describing the association, or extensionally as a set of
associated pairs (argument, result) which are called the graph of the function. Functional programming
also provides greater abstraction for solution. One such a feature is polymorphism which allows general
denition of functions which could be applied to objects of any type. To achieve such a behavior we use
type variables which stand for any type. Further higher order functions provide facility to treat functions
as a data objects and use them like other data objects. It means that function (higher order function) can
manipulate and create other functions. Another important feature of the functional programming is that
evaluation of arguments could be delayed but done at most once. This technique is called lazy evaluation.
Postponing sometimes can lead to such a situation that postponed value could be found as not necessary to
evaluate, even when argument is undened. If such a function can return a dened result we call it non-strict,
else if returns undened is called strict.
1.1.3 Logic
The basic constructs of logic programming, terms and statements are inherited from logic. There are
three basic statements: facts, rules and queries. There is a single data structure: the logical term.
In a logic programming language the logical relationship between various entities are declared. The
programmer writes a database of facts and rules. The user supplies a queries (goals) which the system tries
to prove. This involves matching the current goal against each fact or the left hand side of each rule using
unication. If the goal matches a fact, the goal succeeds; if it matches a rule then the process recurses,
taking each sub-goal on the right hand side of the rule as the current goal. If all sub-goals succeed then the
rule succeeds.
Logic programming languages tend to be declarative programming languages, as opposed to the more
traditional imperative programming languages. In a declarative language, you concentrate on the relation-
ships between the parts of the problem, rather than on the exact sequence of steps required to solve the
problem. An example of a well-known declarative languages are SQL, Prolog.

3.2 1.1.4 Structural


3.3 Two mathematicians, Corrado Bohm and Guiseppe Jacopini proved that any computer
program can be written with the three structures : sequences, decisions and loops. This
discovery led to the method of modern programming known as structured programming.
Structured programming can be seen as a subset or sub discipline of Procedural programming
one of the major paradigms (and probably the most popular one) for Programming computers.
It is possible to do structured programming in almost any procedural programming languages.
Edsger Dijkstra a professor of computer science at the Technological University at Eindhoven proposes
that GOTO statements be abolished from all high-level languages such as BASIC. Modern programming
languages such as Visual Basic do away with the need for GOTO statements.
A computer program is said to be structured if it has a modular design and uses only the three types of
logical structures, sequences, decisions and loops.
Sequences: Statements are executed one after another.
Decisions: One of two blocks of program code is executed based on a test for some condition.
Loops (Iteration): One or more statements are executed repeatedly as long as a specied condition is
true.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 3

One major shortcoming of earlier programming languages was their reliance on the GoTo statement.
This statement was used to branch (that is jump) from one line of the program to another. It was common
for a program to be composed on a convoluted tangle of branching that produced confusing code sometimes
referred to as spaghetti code.
The logic of a structured program can be pictured using a owchart that ows smoothly fro the top to the
bottom without unstructured branching (GoTos). Here is an example of a owchart showing the structure
with and without the GoTo statement:

Ad-
vantages of Structured Programming
The goal of structured programming is to create correct programs that are easy to write, understand and
change.

• Easy to writeModular design increases the programmer's productivity by allowing them to look at the
big picture rst and focus on details later. Several Programmers can work on a single, large program,
each working on a dierent module. Studies show structured programs take less time to write than
standard programs. Procedures written for one program can be reused in other programs requiring the
same task. A procedure that can be used in many programs is said to be reusable

• Easy to debugSince each procedure is specialized to perform just one task, a procedure can be checked
individually. Older unstructured programs consist of a sequence of instructions that are not grouped
for specic tasks. The logic of such programs is cluttered with details and therefore dicult to follow.

• Easy to UnderstandThe relationship between the procedures shows the modular design of the pro-
gram.Meaningful procedure names and clear documentation identify the task performed by each mod-
ule. Meaningful variable names help the programmer identify the purpose of each variable.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 4

• Easy to ChangeSince a correctly written structured program is self-documenting, it can be easily


understood by another programmer.

3.4 Earlier Analysis and Design


As programs got more complex, programmers realized that there might be a better way to write programs
than getting a problem statement and sitting down and writing code. In other words, a little abstract
planning might help. Along these lines, some abstract modeling techniques were developed. Earlier methods
included owcharts and functional specications, functional decomposition. Later techniques involved:

• data ow diagrams (functionality)


• data dictionaries (functionality)
• Decision trees
• process specications (structured English)
• entity relationship diagrams (data  Information modeling)

The later techniques arose from the structured programming languages, and became used in structured anal-
ysis and design. The intention of the models was to create extra levels of abstraction between the real-world
problem/system and the computer implementation of the system. They served as a bridge between the real
world situation, and the computer code. The problem was mapped into a verbal problem statement, and then
into a requirements analysis model, which was far removed from the machine implementation. The analysis
model was then mapped into a design model, which was one step closer to the machine implementation (the
code). Finally, code was written from the design model. However, these earlier abstract models all ran on
one premise  there is data, and there are functions that process the data. The rst models attempted only
to model the functionality of the real-world systems. Later, entity relationship diagrams were added  these
modeled the data, or the static nature of the system. However, the functionality models and the data models
were distinct and separate entities.
1.1.4 Object-oriented
In object-oriented programming programmers dene not only the data type of a data structure, but also
the types of operations (functions) that can be applied to the data structure. In this way, the data structure
becomes an object that includes both data and functions. In addition, programmers can create relationships
between one object and another. For example, objects can inherit characteristics from other objects. Objects
and object interactions are the basic elements of design.
One of the principal advantages of object-oriented programming techniques over imperative programming
techniques is that they enable programmers to create modules that do not need to be changed when a new
type of object is added. A programmer can simply create a new object that inherits many of its features
from existing objects. This makes object-oriented programs easier to modify.
The advantages of object-oriented programming do not evidence themselves when you are writing a single
function for a particular purpose. Instead, the advantages arise when you are designing a large system that
will do similar , but not identical, things to a variety of data objects. By specifying classes of data objects for
which identical eects will occur, you can dene a single generic function that embraces the similarities across
object types, but permits individual implementations or methods for each dened class. As an example of
languages that implements object paradigm are Smalltalk, Delphi and Java.

3.5 OO The Object Oriented Paradigm


Is it possible to make a computer think the way people naturally think, rather than in terms of data and
instructions that process data? The base machine will probably always think in terms of data and instructions
that process data. However, are there high-level languages that can add another layer of abstraction on top
of the machine, so that the high level languages can be written in code that mirrors the way people think?
Yes, of course  these are the OO languages! Some OO languages are better at hiding the basic premise of
the machine. Smalltalk is probably the best, while C++ is probably the worst .

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 5

3.5.1 History of OO languages


First OO language was Simula  1967. Used widely in Europe, it never caught on in the U.S. Then came
Smalltalk  1972. In 1986, Bjarne Stroustrup invented C++, and Brad Cox created Objective-C. OO
languages began taking o at this time. But as of 1994, OO languages have been around for 24 years.
Earlier versions, such as Smalltalk, may have been unpopular because machines weren't powerful enough to
handle them.

3.5.2 What Makes a Language Object-Oriented?


According to Bertrand Meyer, an OO programming language should contain the following 7 qualities [7]:

• The support of modules.


• The modules must support data abstraction, which entails: a.) Information hiding and b.) Encapsu-
lation.
• Automatic memory management (not necessarily garbage collection).
• All data are dened by abstract data type (ADT) based modules. (e.g. classes).
• Ability to extend existing classes (i.e. inheritance).
• Support of polymorphism and dynamic binding.
• Multiple inheritance (the need for this feature in an OO language is disputed by many in the OO eld.)

3.5.3 Objects
Basic building block of OO languages is the object. Like objects of human thought, OO objects combine
both data (nouns and adjectives) and actions (verbs) into one package. Data is implemented as data, while
actions are implemented as functions. The machine still sees a data-functionality split. But the outside
world sees data and functionality merged into one whole.

3.5.4 Classes
OO Languages promote classication at two levels. First, there is the class construct. Classes are like "cookie
cutters" from which objects are moulded. We have a "cat" class from which we create cat objects, each
with dierent attributes. The class species the attributes (and the functionality) while the objects ll in
the attribute values. For example, we have a cat class that has weight, color, and name attributes specied.
From the cat class, we create cat objects, through which the program is actually run.

3.5.5 Inheritance
A looser classication scheme is obtained through inheritance. We can tie in our cat class into a whole
inheritance hierarchy which includes the entire cat family, the mammals, all animals, and then all living
things.

3.5.6 Polymorphism
Polymorphism is the method by which OO languages mirror the human thought processes' tendency to
group certain actions together. We can call similar functionality by the same name  e.g. cats eat and cows
eat, but the way they eat is dierent. However, we still call their actions "eating". OO languages allow
for similar functions (actions) to be given similar names. This allows for conceptual clarity in writing code.
Note that C and other traditional languages use polymorphism to some extent. For example, the arithmetic
operators act on both oating point numbers and integers with the same operators (+, - , /, *, etc) even
though the underlying implementation is radically dierent.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 6

3.5.7 Abstraction
Software objects mirror the human mind's tendency to abstract out details. Software objects hide the
internal details of an object behind the walls of an interface. The "user" or "client" of an object does not
have to worry about the inner details of the object, only the abstract principles of the object, as dened by
the interface.
1.2. The Windows Environment
Windows is a Graphical User Interface (GUI). It uses graphics to organize the user's workspace. User's
choose items and execute programs by pointing and clicking with a mouse. The program that run from within
Windows also have a Graphical User Interface (GUI); for example, MS-Excel and MS-Word. Moreover these
programs can run only within Windows. This is because Windows provides these programs with a number
of built in functions and data which are not available in other environments. The functions that are provided
by windows include functions with the functionality to draw text in dierent sizes and styles using font data.
Windows provides a broad range of graphical functions for drawing lines and geometric shapes and changing
color. Windows program make use of these built in functions and do not have to be coded to perform these
tasks.
These system dened functions that an application can call are provided by an interface known as the
Application Program Interface (API) Every Windows environment has its unique API. For example, the
API that Windows 95 supports (also called the Win32 interface) is a 32-bit API. All the functions supported
by the API can work with 32 bits of information at any given time. Writing programs for the Windows
environment using the API functions is referred to as SDK programming where SDK stands for Software
Development Kit.
1.3
A History of Windows
Windows promised an easy-to-use graphical interface, device-independent graphics and multitasking sup-
port. The development was delayed several times, however, and the Windows 1.0 hit the store shelves in
November 1985. The selection of applications was sparse, however, and Windows sales were modest.
Windows 1.0 package, included
MS-DOS Executive, Calendar, Cardle, Notepad, Terminal, Calculator, Clock, Reversi, Control Panel,
PIF (Program Information File) Editor, Print Spooler, Clipboard, RAMDrive, Windows Write, Windows
Paint.
On November 10, 1983, Microsoft announced Microsoft Windows, an extension of the MS-DOS operating
system that would provide a graphical operating environment for PC users. Microsoft called Windows 1.0
a new software environment for developing and running applications that use bitmap displays and mouse
pointing devices. With Windows, the graphical user interface (GUI) era at Microsoft had begun.
The release of Windows XP in 2001 marked a major milestone in the Windows desktop operating system
family, by bringing together the two previously separate lines of Windows desktop operating systems.
With the upcoming release of Windows .NET Server, Microsoft will complete a cycle of server operating
system upgrades it began nearly a decade ago in 1993, with the release of the rst version of Microsoft
Windows NT Server. To understand the progression of Windows server operating systems you have to look
back earlier than 1993, however, to the even longer line of Windows desktop operating systems stretching
back to the early 1980s.
To explain the many advances since Windows 1.0, the following pages summarize milestones in the
development of Windows desktop operating systems at Microsoft.
Many longtime PC users trace Windows to the 1990 release of Windows 3.0, the rst widely popular
version of Windows and the rst version of Windows many PC users ever tried. But Microsoft actually
released the rst version of Windows six years earlier, in 1985. To understand the roots of today's Windows
operating systems, we must journey back nearly 20 years.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 7

The Windows 1.0 product box showed the new tiled windows and graphical user interface in the operating
system

Table 1

1985: Windows 1.0


The rst version of Windows was a milestone product because it allowed PC users to switch from the
MS-DOS ® method of typing commands at the C prompt (C:\) to using a mouse to point and click their
way through functions, such as starting applications, in the operating system.
Windows 1.0 also allowed users to switch between several programswithout requiring them to quit
and restart individual applications. The product included a set of desktop applications, including the MS-
DOS le management program, a calendar, card le, notepad, calculator, clock, and telecommunications
programs, which helped users manage day-to-day activities.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 8

Even before the Windows 1.0 graphical user interface, there was this pre-Windows 1.0 Interface Manager

Table 2

1987: Windows 2.0


With the second version of Windows, Microsoft took advantage of the improved processing speed of
the Intel 286 processor, expanded memory, and inter-application communication capabilities using Dynamic
Data Exchange (DDE). Windows 2.0 featured support for the VGA graphics standard, and also allowed
users to overlap windows, control screen layout, and use keyboard combinations to move rapidly through
Windows operations.
Many developers started writing their rst Window-based applications for Windows 2.x. Following the
release of Windows 2.0 was Windows/386 2.03, which took advantage of the protected mode and extended
memory capabilities of the Intel 386 processor.
Subsequent Windows releases continued to improve the speed, reliability, and usability of the PC, and
improved the interface design and capabilities.
1990: Windows 3.0
Microsoft's rst mainstream computing platform oered 32-bit performance, advanced graphics, and full
support of the more powerful Intel 386 processor. A new wave of 386 PCs helped drive the popularity of
Windows 3.0, which oered a wide range of new features and capabilities, including:

• Program Manager, File Manager, and Print Manager


• A completely rewritten application development environment with modular virtual device drivers
(VxDs), native support for applications running in extended memory, and fully pre-emptive MS-DOS
multitasking
• An improved set of Windows icons

The popularity of Windows 3.0 blossomed with the release of a completely new Windows software develop-
ment kit (SDK), which helped software developers focus more on writing applications and less on writing
device drivers. Widespread acceptance among third-party hardware and software developers helped fuel the
success of Windows 3.0.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 9

Windows 3.0 featured a new File Manager

Table 3

1993: Windows for Workgroups 3.11


A superset of Windows 3.1, Windows for Workgroups 3.11 added peer-to-peer workgroup and domain
networking support. For the rst time, Windows PCs were natively network-aware and became an integral
part of the emerging client/server computing evolution.
Windows for Workgroups was used in local area networks (LANs) and on stand-alone PCs and laptop
computers. It added features of special interest to corporate users, such as centralized conguration and
security, signicantly improved support for Novell NetWare networks, and remote access service (RAS).
Windows for Workgroups also oered the performance benets of Microsoft's new 32-bit le system.
1993: Windows NT 3.1
The release to manufacturing of Microsoft Windows NT ® on July 27, 1993, marked an important
milestone for Microsoft. It completed a project Microsoft began in the late 1980s to build an advanced new
operating system from scratch. "Windows NT represents nothing less than a fundamental change in the way
that companies can address their business computing requirements.
Windows NT was the rst Windows operating system to combine support for high-end client/server
business applications with the industry's leading personal productivity applications. The operating system
broke new ground in security, operating system power, performance, desktop scalability, and reliability with
a range of key new features. These included a pre-emptive multitasking scheduler for Windows-based appli-
cations, integrated networking, domain server security, OS/2 and POSIX subsystems, support for multiple
processor architectures, and the NTFS le system.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 10

Windows NT 3.1 contained overlapping windows and other features similar to Windows 3.1

Table 4
The new operating system began with version 3.1 in order to maintain consistency with Windows 3.1,
which at the time was a well-established operating system for both home and business users.
Windows NT was geared toward business users and was initially available in both a desktop (workstation)
version and a server version called Windows NT Advanced Server. The desktop version was well received by
developers because of its security, stability, and rich Microsoft Win32 ® application programming interface
(API)a combination that made it easier to support powerful programs.
Windows NT was a strategic platform that could integrate client/server applications with existing
Windows-based desktop applications, or function as a technical workstation to run high-end engineering
or scientic applications.
1993: Windows NT Workstation 3.5
Windows NT Workstation 3.5 supported the OpenGL graphics standard, which helped power high-end
applications for software development, engineering, nancial analysis, scientic, and business-critical tasks.
The Windows NT Workstation 3.5 release provided the highest degree of protection yet for critical busi-
ness applications and data. The product also oered 32-bit performance improvements, better application
support, including support for NetWare le and print servers, and improved productivity features, such as
the capability to give les 255-character names.
1995: Windows 95
Windows 95 was the successor to Microsoft's three existing general-purpose desktop operating systems
Windows 3.1, Windows for Workgroups, and MS-DOS. Windows 95 included an integrated 32-bit TCP/IP
stack for built-in Internet support, dial-up networking, and new Plug and Play capabilities that made it easy
for users to install hardware and software.
The 32-bit operating system also oered enhanced multimedia capabilities, more powerful features for
mobile computing, and integrated networking. In order to keep memory requirements to a minimum, it did
not include support for such features as system-level security or Unicode, which came later.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 11

1996: Windows NT Workstation 4.0


This upgrade to Microsoft's business desktop operating system brought increased ease of use and sim-
plied management, higher network throughput, and a complete set of tools for developing and managing
intranets.
Windows NT Workstation 4.0 included the popular Windows 95 user interface and improved networking
support, providing secure, easy access to the Internet and corporate intranets.
In October 1998, Microsoft announced that Windows NT would no longer carry the initials NT," and
that the next major version of the operating system would be called Windows 2000.
1998: Windows 98
Windows 98 was the upgrade to Windows 95. Described as an operating system that "Works Better,
Plays Better," Windows 98 was the rst version of Windows designed specically for consumers.
Windows 98 enabled users to nd PC- or Internet-based information easily, it opened and closed appli-
cations more quickly, and it included support for reading DVD discs and connecting to universal serial bus
(USB) devices.
1999: Windows 98 Second Edition
Microsoft Windows 98 SE, as it was often abbreviated, was an incremental update to Windows 98. It
oered consumers a variety of new and enhanced hardware compatibility and Internet-related features.
Windows 98 SE delivered an improved online experience with Internet Explorer 5 browser software and
Microsoft Windows NetMeeting ® version 3.0 conferencing software. ®
It also included Microsoft DirectX
API 6.1, which delivered a variety of Windows multimedia improvements, and oered home networking
capabilities through Internet connection sharing (ICS). Windows 98 SE was also Microsoft's rst consumer
operating system capable of using device drivers that also worked with the Windows NT business operating
system.
2000: Windows Millennium Edition (Windows Me)
Windows Me oered consumers numerous music, video, and home networking enhancements and relia-
bility improvements.
System Restore let users roll back their PC software conguration to a date or time before a problem
occurred. Windows Movie Maker provided users with the tools to digitally edit, save, and share home
videos. Microsoft Windows Media — Player 7 technologies allowed users to easily nd, organize, and play
digital media.
Windows Me was the last Microsoft operating system to be based on the Windows 95 kernel. Microsoft
announced that all future operating system products would be based on the Windows NT and Windows
2000 kernel.
2000: Windows 2000 Professional

Figure 1

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 12

Windows 2000 Professional was the upgrade to Windows NT Workstation 4.0, but it was more than
just that. Windows 2000 Professional was designed to replace Windows 95, Windows 98, and Windows NT
Workstation 4.0 on all business desktops and laptops. Built on top of the proven Windows NT Workstation
4.0 code base, Windows 2000 added major improvements in reliability, ease of use, Internet compatibility,
and support for mobile computing.
Windows 2000 Professional also made hardware installation much easier than it was with Windows NT
Workstation 4.0 by adding support for a wide variety of new Plug and Play hardware, including advanced
networking and wireless products, USB devices, IEEE 1394 devices, and infrared devices.
2001: Windows XP
Windows XP is a unifying leap forward for desktop operating systems. With the release of Windows
XP Home Edition and Windows XP Professional in October 2001, Microsoft succeeded in merging its two
Windows operating system lines for consumers and businesses, uniting them around the Windows NT and
Windows 2000 code base.
With Windows XP, consumers and home users now have performance, stability, and security that business
users beneted from in Windows 2000.
Windows XP also includes the broad base of application and hardware compatibility of Windows 98 and
Windows Me, while adding new tech-support technology, a fresh user interface, and many other improvements
that make it easier to use for a broad range of tasks.
Windows XP is available in two main versions, Windows XP Professional and Windows XP Home Edition,
as well as a 64-bit edition, Windows XP 64-Bit Edition, for power users with workstations that use the Intel
Itanium 64-bit processor.
2001: Windows XP Professional
Windows XP Professional benets from the long track record of Microsoft Windows NT technology: supe-
rior operating system performance, including preemptive multitasking, fault tolerance, and system memory
protection.
Windows XP Professional also oers a redesigned interface and includes features for business and ad-
vanced home computing, including Remote Desktop, encrypting le system, system restore and advanced
networking features. It also oers numerous key enhancements such as wireless 802.1x networking support,
Windows Messenger, Remote Assistance, and the System Restore feature.
2001:WindowsXPHomeEdition
Windows XP Home Edition oers a clean, simplied visual design that makes frequently accessed features
more accessible. The product oers many enhancements aimed at home users such as the Network Setup
Wizard, Microsoft Windows Media — Player, Windows Movie Maker, and enhanced digital photo capabilities.
1.4 Windows Programming Model
Programs written for traditional operating environments use a procedural programming model in which
programs execute from top to bottom in an orderly fashion. The path taken from start to nish may vary
with each invocation of the program depending on the input it receives or the conditions under which it is
run, but the path remains fairly predictable. In a C program, execution begins with the rst line in the
function named main and ends when main returns. In between, main might call other functions and these
functions might call even more functions, but ultimately it is the programnot the operating systemthat
determines what gets called and when.
Windows programs operate dierently. They use the event-driven programming model illustrated in Fig-
ure 1.4, in which applications respond to events by processing messages sent by the operating system. An
event could be a keystroke, a mouse click, or a command for a window to repaint itself, among other things.
The entry point for a Windows program is a function named WinMain, but most of the action takes place in a

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 13

function known as the window procedure.


Figure 1.4 Windows Programming Model
The window procedure processes messages sent to the window. WinMain creates that window and
then enters a message loop, alternately retrieving messages and dispatching them to the window procedure.
Messages wait in a message queue until they are retrieved. A typical Windows application performs the bulk
of its processing in response to the messages it receives, and in between messages, it does little except wait
for the next message to arrive.
The message loop ends when a WM_QUIT message is retrieved from the message queue, signaling that
it's time for the application to end. This message usually appears because the user selected Exit from the
File menu, clicked the close button (the small button with an X in the window's upper right corner), or
selected Close from the window's system menu. When the message loop ends, WinMain returns and the
application terminates.
1.5 Dynamic Link Library (DLL)
Dynamic Link Library (DLL) is a collection of software routines programmed in a language such as C or

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 14

Pascal, which has been packaged especially for use from another program. For example, a C programmer
might write a routine that accesses a laser disc player. By compiling this as a DLL, it might be usable by
an author of a Windows Help hyper book, without them having to know anything about the programming.
In windows programming DLL plays an important part. Windows provides function calls to implement its
user interface and display text and graphics on the video display. These functions are implemented in DLL.
These are les with extension .DLL or .EXE.
The original idea for the DLL system was that there would be a central repository of code. Here are the
advantages:

• Applications would link to this code library, thus saving greatly on duplication of eort and storage
space.
• Applications that used the DLL system would behave exactly the same as all other applications that
used it.
• If a problem arose, or a new feature was desired, it could be written once and all would benet. In
this sense, the DLL system is a weak version of the object-programming paradigm.

Naturally enough, along with these advantages came some responsibilities. An application should only place
a DLL in the central repository if:

• The DLL was newer and/or better than the ones already there.
• The DLL was uniquely named, i.e. did not conict with a DLL for another purpose with the same
name.
• If the DLL replaced another with the same name, then the code in the DLL would be exhaustively
tested, so that on replacement, other applications could use it in the same way as its predecessor.

In time, all these rules have been broken, even by Microsoft itself, the originator of the idea.

• On several occasions Microsoft has created and distributed DLL les that instantaneously broke every
Windows application in the world.
• Regularly, end users will install an application that has a DLL with the same name as a "system"
DLL, thus mysteriously bringing down the system until an expert can sort it out.
• Over time, the "synchronization" problem becomes more severe. In this scenario, a DLL is replaced
that brings it into conict with other DLLs it must work with.
• The service pack problem is becoming severe. In this scenario, Microsoft releases a service pack that
updates all key system DLLs. All the elements of the service pack must simultaneously be present in
their most recent form or the system will crash. Then the user installs an application that blithely
replaces one or more of the DLLs from the service pack. Result  system failure, even on Windows NT
4.0, which, notwithstanding its reputation for stability and resilience, will fail utterly and completely.

This is an example of a collision between an idea and reality, a key element in the human drama. The
idea was sound, but it failed to take into account the imperfections in the human character, in particular
those imperfections that inuence the creation and operation of computer programs. The reality is that
Microsoft and any number of software vendors regularly risk the stability and security of the end user's
machine by writing DLL code as though it were normal programming. It isn't. To write a DLL, you must
imagine the eect of your changes and additions on every computer program that uses it. This is obviously
impossible. The solution to these problems is to go back to the system that preceded the DLL system.
Every application should place as many DLL les as possible in its own directory (some DLL les are part
of Windows itself, these must be accessed in common). No application should assume that it can copy DLLs
into the system directory or that its newer version of a system DLL is safe to copy solely because it is
newer. Many applications (including Microsoft's own) have rendered systems unstable or unusable through
this reasoning.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 15

3.6 Win32s DLL Libraries


The Win32s DLL Libraries are an add-on set of programs that expand the MS Windows 3.1 and MS Windows
for Workgroups 3.11 systems so that they can run programs that follow the Win32s standard from MicroSoft.
By allowing them to run Win32s compliant programs, programers can write programs to follow that standard
and have it run, hopefully, on MS Windows 3.1, MS Windows for Workgroups 3.11, MS Windows 95 and
MS Windows NT.
MS DOS and MS Windows 3.1/MS Windows for Workgroups 3.11 run 16-bit coded programs. The limit
to 16-bit allows them to run on older computers with no signicant changes. MS Windows 95 and MS
Windows NT run 32-bit coded programs and do not need DOS at all. The 32-bit code needs at least a 386
IBM Compatible computer to run because the code is 32-bits instead of 16-bits it can:

• Use the full BUS width of the CPU to tranfer more information per computer clock cycle
• Have a more robust command structure with a possible 2^32 ( 4294967296 ) commands. Of course,
at this stage of computer development there is no need for THAT MANY commands. But it is useful
for splitting up common functions into seperate commands that were previously combined or grouping
some common groups of commands into single commands.

In the course of writing and distributing Windows applications, the majority of customer problems were
related to DLLs. If you create a program that assumed that standard Windows system DLLs would be
present, those DLLs would not be present or would not be current, and the application would fail. If I took
it upon myself to follow the DLL guidelines and copy DLLs into the system directory after ascertaining that
my DLL was newer than the current one, other applications would fail. To avoid this problem it is better to
include in the application all required DLLs in the program directory.
1.6 API (Application Programming Interface)
A set of routines, protocols, and tools for building software applications. A good API makes it easier to
develop a program by providing all the building blocks. A programmer puts the blocks together.
API (Application Programming Interface) is a set of commands, which interfaces the programs with the
processors. The most commonly used set of external procedures are those that make up Microsoft Windows
itself. The Windows API contains thousands of functions, structures, and constants that you can declare
and use in your projects. Those functions are written in the C language, however, so they must be declared
before you can use them. The declarations for DLL procedures can become fairly complex. Specically to
C# it is more complex than VB. You can use API viewer tool to get API function declaration but you have
to keep in mind the type of parameter which is dierent in C#.
Most of the advanced languages support API programming. The Microsoft Foundation Class Library
(MFC) framework encapsulates a large portion of the Win32 (API). ODBC API Functions are useful for
performing fast operations on database. With API your application can request lower-level services to
perform on computer's operating system. As API supports thousands of functionality from simple Message
Box to Encryption or Remote computing, developers should know how to implement API in their program.
API\'s has many types depending on OS, processor and functionality.
OS specic API:
Each operating system has common set of API's and some special
e.g.
Windows NT supports MS-DOS, Win16, Win32, POSIX (Portable Operating System Interface), OS/2
console API and Windows 95 supports MS-DOS, Win16 and Win32 APIs.
Win16 & Win32 API:
Win16 is an API created for 16-bit processor and relies on 16 bit values. It has platform independent
nature.
e.g. you can tie Win16 programs to MS-DOS feature like TSR programs.
Win32 is an API created for 32-bit processor and relies on 32 bit values. It is portable to any operating
system, wide range of processors and platform independent nature. Win32 API's has `32' prex after the
library name e.g. KERNEL32, USER32 etc. . .

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 16

All APIs are implemented using 3 Libraries.

• Kernel
• User
• GDI

KERNEL
It is the library named KERNEL32.DLL, which supports capabilities that are associated with OS such
as

• Process loading.
• Context switching.
• File I/O.
• Memory management.

e.g. The GlobalMemoryStatus function obtains information about the system's current usage of both physical
and virtual memory
USER
This is the library named "USER32.DLL" in Win32. This allows managing the entire user interfaces
such as :

• Windows
• Menus
• Dialog Boxes
• Icons etc.

e.g. The DrawIcon function draws an icon or cursor into the specied device context.
GDI (Graphical Device Interface)
This is the library named "GDI32.dll" in Win32. It is Graphic output library. Using GDI Windows
draws windows, menus and dialog boxes.

• It can create Graphical Output.


• It can also use for storing graphical images.

e.g. The CreateBitmap function creates a bitmap with the specied width, height, and color format (color
planes and bits-per-pixel).
1.7 The Programming Environment
The Microsoft Visual C++ package includes more than the C compiler and other les and tools necessary
to compile and link windows programs. It also includes the Visual C++ Developer Studio an environment in
which you can edit your source code, create resources such as icons and dialog boxes and edit, compile, run
and debug your programs. The msdn portion of the Microsoft URL stands for Microsoft Developer Network
which is a program that provides developers with the frequently updated CD-ROMs containing much of
what they need to be on the cutting edge of windows development.
1.7.1 Graphical User Interface Concepts
Since the invention of Graphical User Interface (GUI) is in 1972 from that we have seen a good number
of attempts to dene and build the perfect GUI. GUI consists of number of elements such as:

• The Explorer  Program that manages the GUI.


• The Taskbar  Gray bar across the bottom of the screen. It contains icons representing all active
programs, the clock and various utilities.
• The Start Menu  A one button approach to accessing programs, help, and system settings.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 17

GUIs oer a standard look and feel to application thus reducing development and learning time. A GUI is
an environment that can work with graphic objects and it allows event-based interaction with program for
e.g., clicking on mouse buttons, entering data through a text eld (like for the calculator tool). Each event
triggers the execution of event handler function to take appropriate action. Microsoft Windows a typical
example has the following components.

• Menus (Including placement and names of options and styles such as pull down or popup).
• Icons (for identifying application and resources).
• Tiled Windows (for views of multiple programs or data or for multiple views of a single program or a
data block).
• Dialog Boxes (for selecting les, options and settings when an option is selected, the one previously
selected is turned o ).
• Check Lists (from which the user can make multiple selections as in specifying print or le attributes).
• Support for a pointing device, typically a mouse (especially to select and drag screen elements).
• Scroll bars (along the edges to show the relative position of the contents such as the end or beginning
of the text or to move to a dierent position such as another part of a spread sheet).

A GUI enforces consistency by restricting developers they must support features for the program to run under
the GUI. In addition one benet of GUI is that the user can learn a second application faster because he or
she is familiar with the environment. Note that the benet comes with succeeding applications. Consistency
and familiarity help produce shorter learning curves. Users generally prefer the interface style they know,
whether it be Macintosh or Microsoft Windows. The consistency oered by a GUI trades on the users
familiarity with the environment.
Drawing and CAD programs are the best suited to GUI. Since, by their nature they manipulate objects
lines and curves, ll closed areas with color. For database programs, such manipulation is not as useful.
However they can use GUIs eectively to:

• Specify data elds when setting up reports.


• Select sort keys.
• Transfer data to or from other applications (such as a spread sheet).

The last point is particularly important. Database applications often must transfer data to and from spread-
sheets, word processors, desktop publishing programs, business or presentation graphics programs, statistics
programs or project management software. GUIs generally have data exchange features, such as Microsoft
windows dynamic data exchange (DDE) to handle such transfers.
A nal benet of GUI is that it lets you see the nal product before you print it. What You See Is What
You Get (WYSIWYG) is a feature essential to desktop publishing and drawing applications and useful in
database applications (so you can inspect reports to see that all data ts on the page).
However there are drawbacks associated with using GUI. The cost includes the expense of graphics cards,
pointing device (such as mouse) and extra memory. Because GUIs run in graphics mode, screen refresh is
usually slower as well. If speed is important, a GUIs consistency may not be sucient compensation.
1.8 Event Driven Programming
While your program was looking for a particular kind of input, be it a mouse click or a key press, it
wasn't doing any other work. If at a particular place in your program you were looking for a mouse click
and a key was pressed, generally the key press was ignored (at least at that instant). While this approach to
programming is functional in many situations, it does not work very well when there are multiple possible
sources of input whose arrival time you cannot predict and where it is unacceptable to ignore any of the
inputs. As an example consider the case of a VCR.
On a typical VCR there are a number of buttons, sensor inputs for tape in and the end of the tape as
well as commands that can be received from the remote control. The program for the embedded computer
controlling the VCR must be able to respond to any of those inputs at any time and in any sequence. For
example, while running fast forward, you can stop, play, change channels, and program the VCR to record

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 18

or any number of other actions. The program cannot move to only looking for the channel select buttons
while you are programming, or it would miss the end of tape sensor for the rewinding tape.
Clearly, what we need is a program structure that will allow us to respond to a multitude of possible
inputs, any of which may arrive at unpredictable times and in an unpredictable sequence. While this problem
is very common in embedded systems, like the VCR, it is also very common in modern desktop computers.
Think about using a word processor. While you are typing, the program is accepting your keys and entering
the characters into your document. You can also click with the mouse at any place on the screen. If the
mouse pointer is at another place in your document, the point of insertion moves. If it is in the menu bar,
a menu will drop down. If it is over a formatting button, it may change the format of the next character
entered. Your word processor, or most other programs running under Windows, MacOS, X-Windows or any
other modern Graphical User Interface(GUI), must also be capable of dealing with the same kind of variable
input that the VCR must handle. All of these operating systems, and many embedded applications, have
adopted a common program structure to deal with the need to respond to many asynchronous (not time
sequence) inputs. This program structure is generally called event driven programming.
Under the event driven programming model, the program structure is divided into two rough groups,
Events and Services. An event represents the occurrence of something interesting. A service is what you do
in response to the event. While events most often originate from the outside your program, such a mouse
click, events can also generated by other parts of the program. The program executes by constantly checking
for possible events and, when an event is detected, executing the associated service.
In order for this approach to work, the events must checked continuously and often. This implies that
the services must execute quickly, so that the program can get back to checking for events. In order to meet
this requirement, the service can not to go into a state where it is waiting for some long or indeterminate
time. The most common example of this would be a while loop where the condition for termination was not
under program control, for example; a switch closure. This kind of program structure, an indenite loop is
referred to as `Blocking ` code. In order for the even t driven programming model to work, you must only
write `Non-Blocking' code. So how to deal with the need to wait for the switch close? You make the switch
closure an event. Then, rather than waiting in a loop for the switch to close, you program a service that
does the right thing when the switch closes and let all of the event checkers run while you are waiting for
the switch to close. In this way, you could also react to another event while you were waiting for the switch
to close.
Event Checkers
An event, by its nature, represents a discrete point in time. At one instant, the event has not occurred
, at the next it has. In the case of a switch, the opening or closing of the switch represents an event. The
switch being open or closed does not represent an event. The event is marked by the transition from open
to closed.
1.9 Header Files
Windows programs begin with a processor directive at the top such as :
#include <windows.h>
WINDOWS.H is a master le that includes other Windows header les, some of which also include other
header les. The most important and most basic of these header les are:

• WINDEF.H Basic type denitions.


• WINNT.H Type denitions for Unicode support.
• WINBASE.H Kernel functions.
• WINUSER.H User interface functions.
• WINGDI.H Graphics device interface functions.

These header les dene all the Windows data types, function calls, data structures and constant identiers.
They are important part of Windows documentation.
1.10 Program Entry Point
In windows program the entry point is WinMain similar to the main function in C program. The WinMain
function appears like this:

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 19

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine,


int nCmdShow)
It is declared in WINBASE.H like so (line breaks and all) :
int
WINAPI
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd
);
This declaration uses a system called Hungarian notation through which the variable name is indicated
with a short prex that indicates the variables data type. This notation will be discussed later. The rst
parameter to WinMain is an instance handle. In windows programming a handle is simply a number
that an application uses to identify something. In this case the handle uniquely identies the program. It
is required as an argument to some other windows function calls. In early versions of windows when you
run the same program concurrently more than once, multiple instances of that program will be created. A
program can determine if other instances of itself are running by checking the hPrevInstance parameter. In
32 bit versions this concept has been abandoned.
The second parameter to WinMain is always NULL (dened 0). The third parameter to WinMain is
command line used to run the program. The fourth parameter to WinMain indicates how the program
should be initially displayed either normally or maximized to ll the window or minimized to be displayed
in the task list bar.
1.11 Compile, Link and Run Windows program
When you are ready to compile your program named samplewinprg, you can select Build samplewin-
prg.exe from the Build menu or press F7, or select the Build icon from the Build toolbar. The appearance
of this icon is shown in the Build menu. If the Build toolbar is not currently displayed you can choose
Customize from the tools menu and select the Toolbars tab. Pick Build or Build MiniBar. Alternatively
you can execute samplewinprg.exe from the Build menu by pressing Ctrl+F5 or click the Execute program
icon. From the Build toolbar. A message will be displayed asking if you want to build the program.
During compilation the compiler generates an .OBJ(object) le from the C source code le. During the
ling stage the linker combines the .OBJ le with .LIB(library) les to create the .EXE(executable) le. You
can see a list of these library les by selecting settings from the Project tab and clicking the Link tab. In
particular you'll notice KERNEL32.LIB, USER32.LIB, and GDI32.LIB. These are import libraries for the
three major Windows subsystems. They contain the dynamic-ling library names and reference information
that is bound in to the .EXE le. Windows uses this information to resolve calls from the program to
function in the KERNEL32.DLL, USER32.DLL and GDI32.DLL dynamic link libraries. In Visual C++
Developer Studio, you can compile and link the program in dierent congurations. By default these are
called Debug and Release.
1.12 MessageBox Function
The MessageBox function is designed to display short messages. The window that a MessageBox displays
is considered to be a dialog box. The rst argument to MessageBox is normally a window handle. The
second argument is the text string that appears in the body of the message box and the third argument is
the text string that appears in the caption bar of the message box. The fourth parameter can be any of the
combination of constants beginning with the prex MB_ that are dened in the WINUSER.H. The list of
buttons that can appear in dialog box are:
MB_OK
MB_OKCANCEL
MB_ABORTRETRYIGNORE
MB_YESNO
MB_YESNOCANCEL

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 20

MB_RETRYCANCEL
The appearance of the icon in the message box can be any one of the following:
MB_ICANHAND
MB_ICONEXCLAMATION
MB_ICONASTERISK
1.13 Data Types
Windows programming has a reputation for its variety of data types, it uses all C data types and also
introduces a few data types of its own. The sample windows application illustrated in this chapter uses a
few of the Windows data types.
The following code displays a message as displayed in gure 2.10(a)
# include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,
int nCmdShow)
{int i;
MessageBox(0,"Application executing","Application",MB_OK);
return(0);
}

Figure 2.10(a) Sample Output


In this program, the MessageBox function returns the value 1, but it is more proper to say that it returns
IDOK, which is dened in WINUSER.h as equaling 1.Each running copy of a program is called an instance.
To refer to a particular instance of a program, a handle is required. A handle is an unsigned integer that
Windows uses internally to keep track of objects in memory. For example, every window on the screen has
a unique window handle. Handles are also used to keep a track of running applications, allocated memory
blocks and a host of other objects.
A handle is simply a number assigned by the system to a particular entity. It serves to identify the entity,
whether it is an instance, a window, a control or a block of memory. All objects in windows are referred to
by handles. Handles are a replacement of pointers. There are a number of related data types for describing
dierent kinds of handles. All these data types begin with the letter H. Thus, HWND is the data type for a
window handle, and HPEN is the handle to PEN. In the program shown above, hInstance is the handle that
identies the current instance of the application and hPrevInstance contains the hInstance value for the last
copy of application.
Internally the Kernel of windows maintains tables that allow windows to convert handles to physical
memory addresses. A handle is a pointer to a memory location. The reason for this complexity is that
windows moves objects (memory blocks, programs and so on) in memory to make room for others. If
windows moves and object in memory, the handle table is updated. The handle used by the program does
not need to change since it always gets correctly translated to the right physical memory addresses by the
windows kernel, no matter where the object is moved in memory. Figure 2.10(b) displays a representation
of handles in the memory.
Program Windows Kernel Memory
HandleHandle TablePhysical Address
Figure 2.10(b) Handles in the Memory
If a pointer was used to refer to an object in memory, the pointer will be invalid when the object is moved
by windows as a part of its memory management. Thus pointers can be dereferenced whereas handles will

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 21

continue to be valid since the handle to pointer table will be updated automatically by windows whenever
it moves an object in memory.
In the above program, LPSTR is another new windows data type that is used; it is used to store a Long
Pointer to a String same as the char data type of C. The MessageBox function of the Win32 API displays
a message on the screen, with the specied title and message text, the message displayed will show an OK
button also, which will dismiss the MessageBox as specied by the MB_OK parameter.
1.14 Hungarian Naming Convention
The names of the variables used in a window program follow a naming convention called Hungarian
notation, in honor of its inventor Charles Simonyi. The idea is to precede variable names with key letters
that describe the type of data the variable represents and follow a verb-noun combination. The Table 1.14
represents the Hungarian notations.
Table 1.14 Variable Name Codes in Hungarian Notation

Variable Name PrexCode Data Type

b BOOL(Boolean). The variable here can take either True or False values.

by BYTE(unsigned character)

c Char(character)

dw DWORD(double word)

fn Function

h Handle

i int(integer)

l Long

n Short(int) or near pointer

p Pointer

s Character string

sz Character string terminated by zero

w Word(two bytes)

Table 5
1.15 Windows String Functions

4 The collection of string functions included in windows to calculate string length,


copy string, concatenate strings and compare strings are listed below:
5 lstrcmpi - Compares two strings, ignoring case.
6 lstrcmp  Compares two strings.
7 lstrcpyn - Copies one string to another, with a maximum length.
8 lstrcpy - Copies one string to another.
9 lstrlen - Gets the length of a string in characters.
10 lstrcmpi
Compares two character strings. The comparison is not case sensitive.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 22

Syntax
int lstrcmpi(LPSTR lpszString1,LPSTR lpszString2);
The rst parameter lpszString1 is the pointer to the rst null-terminated string to be compared. The
second parameter lpszString2 is the pointer to the second null-terminated string to be compared. This
function returns a negative value if the function succeeds and the string that lpszString1 points to is less
than the string that lpszString2 points to. Returns a positive value if the string that lpszString1 points to
is greater than the string that lpszString2 points to. Returns zero if the strings are equal. The lstrcmpi
function compares two wide strings by checking the rst characters against each other, the second characters
against each other, and so on until it nds an inequality or reaches the ends of the strings. Similarly two wide
strings can be compared using the function lstrcmpiW and also the wide character string can be represented
using LPCWSTR (long pointer to wide character string).

11 lstrcmp
Compares two strings. The comparison is case sensitive.
Syntax
int lstrcmp(LPSTR lpszString1,LPSTR lpszString2);
The rst parameter lpszString1 is the Pointer to the rst null-terminated wide string to be compared.
The second parameter lpszString2 is the Pointer to the second null-terminated wide string to be compared.
Returns a negative value if the function succeeds and the string that lpszString1 points to is less than the
string that lpszString2 points to. Returns a positive value if the string that lpszString1 points to is greater
than the string that lpszString2 points to. This function returns zero if the strings are equal. The lstrcmp
function compares two strings by checking the rst characters against each other, the second characters
against each other, and so on until it nds an inequality or reaches the ends of the strings. Similarly two
wide strings can be compared ignoring case using the function lstrcmpW.

12 lstrcpy
Copies a string to a buer.
Syntax
LPSTR lstrcpy(LPSTR lpszString1,LPSTR lpszString2);
The rst parameter lpszString1 is the Pointer to a buer to receive the contents of the string pointed to by
the lpszString2 parameter. The buer must be large enough to contain the string, including the terminating
wide null character. The second parameter lpszString2 is the pointer to the null-terminated wide string to
be copied. This function returns a pointer to the buer. Similarly two wide strings can be copied using the
function lstrcpyW.

13 lstrcpyn
Copies a string to a buer, up to a specied number of characters.
Syntax
LPSTR lstrcpyn(LPSTR lpszString1,LPSTR lpszString2,int iMaxLength);
The rst parameter lpszString1 is the pointer to a buer to receive the contents of the string that the
lpszString2 parameter points to. The buer must be large enough to contain the string, including the
terminating wide null character. The second parameter lpszString2 is the pointer to the null-terminated
string to be copied. The third parameter iMaxLength gives the maximum number of characters to copy,
including a terminating null character. This function returns a pointer to the buer. If iMaxLength is
nonzero, lstrcpyn always inserts a terminating null character in the destination string, which could result in
the source string being truncated. Similarly lstrcpynW copies a wide string to a buer, up to a specied
number of wide characters.
lstrlen

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 23

Retrieves the length of the specied string.


Syntax
int lstrlen(LPSTR lpszString);
The rst parameter lpszString is the pointer to a null-terminated wide string. If the function succeeds,
the return value species the length of the string. Similarly lstrlenW retrieves the length of the specied
wide string.
1.16 The Sample SDK Program
Creating a window rst requires registering a window class and that requires a window procedure to
process messages to the window. This involves a bit of overhead that appears in almost every windows
program. The program shown below is a simple program that handles only three windows messages(two
mouse click messages and a quit message). Figure 1.16(a) shows the applications only window.

Figure 1.16 (a) A Minimal Windows Program written using SDK


// Sample SDK program to display window
#include <windows.h>
WNDCLASS wc;
MSG msg;
HWND hwnd;
LRESULT CALLBACK wndproc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,
int nCmdShow)
{
wc.style=CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc=wndproc;
wc.hInstance=hInstance;
wc.hCursor=LoadCursor(hInstance,IDC_ARROW);
wc.hIcon=LoadIcon(hInstance,NULL);
wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszClassName ="Sample";
wc.lpszMenuName =NULL;
if (!RegisterClass(&wc))
return false;
hwnd=CreateWindow(Sample,AsampleSDK Window,

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 24

WS_OVERLAPPEDWINDOW,//window style
CW_USEDEFAULT, //initial x position
CW_USEDEFAULT, //initial y position
CW_USEDEFAULT, //initial x size
CW_USEDEFAULT, //initial y size
NULL,//parent window handle
NULL,//window menu handle
HINSTANCE,//program instance handle
NULL);//creation parameters
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true;
}
LRESULT CALLBACK wndproc(HWND hwnd,UINT wm,WPARAM wp,LPARAM lp)
{
char left[]="You have pressed left mouse button";
char right[]="You have pressed right mouse button";
switch(wm)
{
case WM_LBUTTONDOWN:
{
MessageBox(GetFocus(),left,"About",MB_OK|MB_ICONINFORMATION);
break;
}
case WM_RBUTTONDOWN:
{
MessageBox(GetFocus(),right,"About",MB_OK|MB_ICONINFORMATION);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
default:
break;
}
return(DefWindowProc(hwnd,wm,wp,lp));
}

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 25

Figure 1.16 (b) The sample SDK program responding to a left mouse click message
1.16.1Dissecting the Program
The code for this program deserves a closer examination. The program starts with #include<windows.h>.
This statement includes the main windows header le(WINDOWS.H) that in turn includes all the windows
header le that contain structures, macros, API prototypes and everything else that the SDK program needs.
Then the two SDK functions declared are: the program entry point WinMain() and the application's window
procedure in this case wndproc. However there is a reference to wndproc in WinMain, which is why the
function is declared near the top of the program.
Windows function calls
The sample SDK windows program makes calls to fewer windows functions. These functions with a brief
description are:

• Load IconLoads an icon for use by a program.


• Load CursorLoads a mouse cursor for use by a program.
• GetStockObjectObtains a graphic object in this case a brush used for painting the windows background.
• RegisterClassRegisters a window class for the program's window
• MessageBoxDisplays a message box.
• CreateWindowCreates a window based on a window class.
• ShowWindowShows the window on the screen.
• UpdateWindowDirects the window to paint itself.
• GetMessageObtains a message from message queue.
• TranslateMessage Translates some keyboard messages.
• DispatchMessage Sends a message to a window procedure.
• PostQuitMessage To insert a quit message in to the message queue.
• DefWindowProc Performe default processing of messages.

Window Class Structure(WNDCLASS)


The WNDCLASS structure is used to dene all windows that you can view on your monitor. The
structure of a window class looks like this:
typedef struct_WNDCLASS
{UINT style; //window class style
WNDPROC lpfnWndProc; //window procedure

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 26

int cbLlsExtra; //extra class bytes


int cbWndExtra; //extra window bytes
HANDLE hInstance; // instance handle
HICON hIcon; // icon handle
HCURSOR hCursor; // cursor handle
HBRUSH hbrBackground; // background brush color
LPCTSTR lpszMenuName; // menu resource
LPCTSTR lpszClassName; // window class name
}WNDCLASS ;
Message Structure
Because almost everything in windows happens in response to messages, the windows message structure
MSG is extremely important. This structure is dened as follows:
typedef Struct tagMsg
{HWND hwnd; // handle of the windows to retrieve messages
UINT message; // message value for each windows identied by macros in WINDOWS.H
WPARAM wp; // additional information about the message
DWORD time; //time at which the message was posted to the queue
POINT pt; // screen coordinates of the cursor when the message was posted
}MSG;
Uppercase Identiers
These identiers are dened in the windows header les. The identiers contain a two-letter or three-letter
prex followed by an underscore:
CS_HREDRAWDT_VCENTERSND_FILENAME
CS_VREDRAWIDC_ARROWWM_CREATE
CW_USEDEFAULTIDI_APPLICATIONWM_DESRTOY
DT_CENTERMB_ICONERRORWM_PAINT
DT_SINGLENAMESND_ASYNCWS_OVERLAPPEDWINDOW
These are simply numeric constants. The prex indicates a general category to which the constant
belongs.

• CS Class style option


• CW Create window option
• DT Draw text option
• IDI ID number for an icon
• IDC ID number for a cursor
• MB Message box options
• SND Sound option
• WM Window message
• WS Window style

Initializing and Registering the Window Class


Windows allows multiple instances of a single application to run concurrently each application window has
a window class. A window class must be initialized and registered when the rst instance begins execution. If
there are no previous instances of the application running the WNDCLASS structure variable wc is initialized
with values and registered with windows by calling the RegisterClass() API function with a pointer to wc as
the only parameter. Here is the way to handle the RegisterClass function call:
if(!RegisterClass(&wc)
return false;
In some sample windows programs you may see the following code in WinMain:
If(!hPrevInstance)
{wc.style=CS_HREDRAW | CS_VREDRAW;

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 27

[ other wndclass initialization]


RegisterClass(&wc);
}
This declaration is necessary only for 16 bit version of windows, if you started up a new instance of a
program that was already running then the hPrevInstance parameter should be the instance handle of the
previous instance. The window class can be registered only if hPrevInstance was NULL, indicating no other
instances of the program were running. But in 32 bit versions of windows hPrevInstance is always NULL, it
is not necessary to check hPrevInstance.
Creating the Window
The application window is created by calling the API function CreateWindow(). The CreateWindow()
function takes 11 parameters. Here's the CreateWindow call with comments identifying the parameters.
hwnd=CreateWindow( SZAPPNAME, // window class name
SZAPPTITLE, // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
HINSTANCE, // program instance handle
NULL); //creation parameters
The window created by this program is a normal overlapped window. It will have a title bar, system menu
button to the left of the title bar, a thick window sizing border and minimize, maximize and close buttons to
the right of the title bar. This is the standard style for windows. By using the identier CW_USEDEFAULT
to indicate (initial x , y position and initial x , y size) we are indicating that we want windows to use the
default position for an overlapped window.
The argument marked parent window handle is to set to NULL when creating a top level window
such as an application window. Normally, when a parent-child relationship exists between two windows the
child window always appears on the surface of its parent. The window menu handle is also set to NULL
because the window has no menu. The program instance handle is set to the instance handle passed to the
program as a parameter of WinMain. Finally a creation parameter is set to NULL. The CreateWindow
function call returns a handle to created window which is stored in the variable hwnd. It is dened to be of
type HWND (handle to a window).
Displaying the Window
After the CreateWindow call returns the window has been created internally in windows. However the
windows do not yet appear on the video display, two more calls are needed. They are:
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
The ShowWindow call determines how to display the window on the screen., whether it is normal,
minimized or maximized. The rst argument is the handle to the window just created by CreateWindow.
The second argument nCmdShow is the value passed as a parameter to WinMain which determines how the
window is to be internally displayed on the screen whether it is normal, minimized or maximized. This can
be done by dening the second parameter to have one of the elds given below:

• SW_SHOWMAXIMIZED - To display maximized window.


• SW_SHOWMINIMIZED  To display minimized window.
• SW_SHOWNORMAL  To display normal window.
• SW_SHOWMINOACTIVE  To display the window in task bar.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 28

If the second argument to ShowWindow is SW_SHOWNORMAL the client area of the window is erased
with background brush specied in the window class. The function call UpdateWindow causes the client
area to be painted.
Window Procedure
The window procedure determines what the window displays in its client area and how the window
responds to user input. A windows program can contain more than one window procedure. The window
procedure can be dened like this:
LRESULT CALLBACK wndproc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
These parameters are identical to the rst four elds of the MSG structure. The rst parameter hwnd
is the handle to window receiving the message. If a program creates multiple windows based on the same
window class and hence the same window procedure, hwnd identies the particular window receiving the
message. The second parameter is a number that identies the message. The last two parameters are 32 bit
message parameters that provide more information about the message.
Handling Messages in Window Procedure
After the UpdateWindow call the window is fully visible in the screen. The program must now make
itself ready to read input from the user through mouse and keyboard. Message queue is maintained for each
windows program currently running under windows. When an input event occurs windows translates the
event in to a message that it places in the message queue. The messages can be retrieved from the message
queue by executing the message loop:
While(GetMessage(&msg,NULL,0,0))
{ TranslateMessage(&msg);
DispatchMessage(&msg);
}
The GetMessage call retrieves a message from a message queue and passes to window a pointer to a MSG
structure named msg.
The TranslateMessage call passes the msg structure back to windows for some keyboard translation.
The DispatchMessage call passes the msg structure back to windows and the windows then sends the
message to the appropriate window procedure for processing.
Every message that window procedure receives is identied by a number. This is dened with the identi-
ers beginning with the prex WM(Window Message) for each type of message. This can be done through
switch and case statement. To process a message, the window procedure should return 0. All the messages
not to be processed must be passed to a windows function named DefWindowProc. The value returned from
DefWindowProc must be returned from the window procedure. In the sample windows program, wndproc
chooses to process four messages: WM_CREATE, WM_LBUTTONDOWN, WM_RBUTTONDOWN and
WM_DESTROY. The messages can be dened like this:
switch(msg)
{ case WM_CREATE:
[process WM_CREATE message]
return 0;
case WM_LBUTTONDOWN :
[process WM_LBUTTONDOWN message]
return 0;
case WM_RBUTTONDOWN :
[process WM_RBUTTONDOWN message]
return 0;
case WM_DESTROY :
[process WM_DESTROY message]
return 0;
}
return DefWindowProc(hwnd,msg,wp,lp);
Windows Messages

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 29

Windows messages are sent by Windows to your application. These messages begin with the WM_
prex. The WM_* messages are sent by windows and are usually handled by windows and views, some
of the commonly processed windows messages are: WM_COMMAND, WM_CHAR, WM_DESTROY and
WM_QUIT message.
WM_COMMAND Message
This message noties the program that the user has selected a menu item, a child window control or has
used an accelerator key. An accelerator key is a key combination which is used to invoke the options of a
menu and other controls.
WM_CHAR Message
This message is used to retrieve ASCII keyboard inputs such as letters, numbers and printable symbols.
This message is generated when the user presses a character with an ASCII value on keyboard.
WM_DESTROY Message
This message noties the program that a window is being destroyed after it is removed from the screen.
The message is sent after the window image is removed from the screen. For example WM_DESTROY is
sent to the parent window before a child window is destroyed.
WM_QUIT Message
This message indicates a request to terminate an application and is done when the application calls the
PostQuitMessage function. It causes the GetMessage function to return a zero and drop out from message
loop. The return statement exits from WinMain and terminates the program.
Exercises 1

1. Dierentiate Structured Programming and Object Oriented Programming.


2. Dene Object and Class.
3. Explain the Windows Programming Model.
4. What is DLL?
5. What is API?
6. Explain the GUI concepts.
7. Write short notes on Event Driven Programming.
8. What is Hungarian Notation?
9. Write short notes on Windows String Functions.
10. Explain the Message function calls used in Windows Programming.
11. Write the Window Class structure, Message structure and explain them.
12. Explain how to register the Window class.
13. List out the options available to display the Window.
14. Write short notes on Window Procedure.
15. Write about the Windows Messages.

Chapter  2
Basics of GDI and DC

14 2.1Graphics Device Interface (GDI)


The graphics device interface (GDI) provides functions and related structures that an application can use to
generate graphical output for displays, printers, and other devices. Using GDI functions, you can draw lines,
curves, closed gures, paths, text, and bitmap images. The color and style of the items you draw depends
on the drawing objects  that is, pens, brushes, and fonts  that you create. You can use pens to draw
lines and curves, brushes to ll the interiors of closed gures, and fonts to write text.
Applications direct output to a specied device by creating a device context (DC) for the device. The
device context is a GDI-managed structure containing information about the device, such as its operating
modes and current selections. An application creates a DC by using device context functions. GDI returns
a device context handle, which is used in subsequent calls to identify the device. For example, using the

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 30

handle, an application can retrieve information about the capabilities of the device, such as its technology
type (display, printer, or other device) and the dimensions and resolution of the display surface.
Applications can direct output to a physical device, such as a display or printer, or to a "logical" device,
such as a memory device or metale. Logical devices give applications the means to store output in a form
that is easy to send subsequently to a physical device. After an application records output in a metale, it
can play that metale any number of times, sending the output to any number of physical devices.
Applications use attribute functions to set the operating modes and current selections for the device.
The operating modes include the text and background colors, the mixing mode (also called the binary raster
operation) that species how colors in a pen or brush combine with colors already on the display surface, and
the mapping mode that species how GDI maps the coordinates used by the application to the coordinate
system of the device. The current selections identify which drawing objects are used when drawing output.
Figure 2.1 shows the diagrammatic representation of GDI.

Application obtains aGDI uses DC to locate


DC handle from the correct window or
Windows GDI anddevice driver and perform
Passes it to all GDIrequested function.
Functions
Figure 2.1 Graphics Device Interface

14.1 2.2 Device Context


Returns an integer that identies the device-context of window if it has one, or nil otherwise. A device-
context is a construct used in the Windows API to specify a set of parameters that are used when drawing on
a window. A common graphics application does not normally need to deal with a window's device-context
directly, but if you need to pass the window to a WINAPI function that calls for the window's device-context
(or hDC), then you should pass the integer returned by this function for that argument. Every non-control
window in common graphics (and every lisp-widget window) is automatically assigned a device-context,
which it keeps until it is closed. Controls supplied by the OS (all controls except lisp-widgets), on the other
hand, are not automatically given device-contexts in lisp since it is normally only the OS rather than lisp
that draws on the control. If you do want to draw directly on a non-lisp control, then you must give the
window of the control a device-context while drawing on it.

14.2 2.3 The WM_PAINT message


The WM_PAINT message is a request to repaint the window. Every application is responsible for redrawing
its window(s). This means that the application will have to keep track of the current state, so that it knows
that to draw. In most cases, the WM_PAINT message will be triggerd from the outside. However, it is also
possible to trigger WM_PAINT from inside the application. With the Invalidate() function, you can tell that
the contents of a window are no longer valid so that it will need to be redrawn. With the InvalidateRect()
function, you can specify that only part of the window content is invalid, so that only that part will be
redrawn. In this way, you can prevent the ickering of the screen when redrawing. Because paint message
have very low priority, you might want to send an immediate redraw request. You can do this with the
UpdateWindow() function.
2.4 Getting a Device Context Handle

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 31

There are two methods in getting a Device Context handle. The rst method is by processing WM_PAINT
messages. Two functions involved in this process are BeginPaint and EndPaint. These functions require the
handle to window, which is passed to the window procedure as an argument and the address of a structure
variable of type PAINTSTRUCT which has to be dened within the window procedure like so:
PAINTSTRUCT ps; // where ps is the paint structure variable
While processing a WM_PAINT message the window procedure rst calls the function BeginPaint which
causes the background of the invalid region to be erased and prepare the window for painting. This function
lls the elds of the paint structure. The value returned by BeginPaint is a device context handle. This
value can be stored in a variable commonly named as hdc, which has to be dened in window procedure like
so:
HDC hdc; // handle to DC
HDC is a data type dened as a 32 bit integer. After the denition of HDC the program can use functions
like TextOut. The call to EndPaint releases the device context handle. The processing of WM_PAINT
message looks like this:
case WM_PAINT:
hdc = BeginPaint(hwnd,&ps);
[ GDI functions]
EndPaint (hwnd,&ps);
return 0;

15 2.5 The Paint Structure(PAINTSTRUCT)


The PAINTSTRUCT structure contains information for an application. This information can be used to
paint the client area of a window owned by that application.
typedef struct tagPAINTSTRUCT { // ps
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT;

• hdc Handle to the display DC to be used for painting.


• fErase Species whether the background must be erased. This value is nonzero if the application should
erase the background. The application is responsible for erasing the background if a window class is
created without a background brush. For more information, see the description of the hbrBackground
member of the WNDCLASS structure.
• rcPaint Species a RECT structure that species the upper left and lower right corners of the rectangle
in which the painting is requested.
• fRestore Reserved; used internally by the system.
• fIncUpdate Reserved used internally by the system.
• rgbReserved Reserved used internally by the system.

Windows erases the background using the brush specied in the hbrBackground eld of the WNDCLASS
structure that is used when registering the window class during WinMain initialization. Many windows
programs specify a white brush for the windows background. This is indicated in the program with the
statement like this:
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
The second method to get a handle to DC of the client area of the windows js by calling GetDC to obtain
the handle and ReleaseDC to release the handle. This can be done with the statement like this:
hdc = GetDC (hwnd) ;

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 32

[ GDI functions]
ReleaseDC (hwnd,hdc);
The functions GetDC and ReleaseDC should be called in pairs like BeginPaint and EndPaint. GetDC
is used while processing message and ReleaseDC is used to exit the window procedure. Do not call GetDC
in one message and ReleaseDC in another message. A function similar to GetDC is GetWindowDC. While
GetDC returns a device context handle for writing on the client area of the window, GetWindowDC returns
a device context handle for writing on the entire window.To use the function GetWindowDC your program
has to process WM_NCPAINT (non client paint) message.

16 2.6 TextOut
The TextOut function writes a character string at the specied location, using the currently selected font,
background color, and text color.
BOOL TextOut(
HDC hdc, // handle to device context
int x, // x-coordinate of starting position
int y, // y-coordinate of starting position
LPCTSTR lpString, // pointer to string
int cbString // number of characters in string
);
The rst argument is the handle to the device context either the hdc value returned from GetDC or
from BeginPaint during the processing of a WM_PAINT message. The second and third arguments x and
y denes the starting point of the character string within the client area. The fourth argument lpsring is a
pointer to character string and the last argument cbString indicates the number of characters in the string.
Eg: TextOut (hdc,x,y,LeftButtonPressed,17);
2.7 System Font and Text Metrics
The device context denes the font that windows uses to display the text when TextOut function is
called. The default font is a system font which is used by windows for text strings in title bars, menus and
dialog boxes. In earlier versions of windows the system font was a xed pitch font in which all the characters
had the same width. But now the system font is a raster font which means that the characters are dened
as blocks of pixels. The size of a character is based on the size of the video display.
To display multiple lines of text by using the TextOut function the dimensions of characters in the font
should be known The successive lines of the text can be spaced based on the height of the characters and
the columns of the text can be spaced on the average width of the characters. Just as a program can
determine information about the sizes or metrics of user interface items by calling the GetSystemMetrics
function, a program can determine font sizes by calling GetTextMetrics. GetTextMetrics requires a handle
to a device context because it returns information about the font currently selected in the device context.
The TEXTMETRIC structure has 20 elds but only the rst seven elds are essential.
typedef struct tagTEXTMETRIC
{
LONG tmHeight;
LONG tmAscent;
LONG tmDescent;
LONG tmInternalLeading;
LONG tmExternalLeading;
LONG tmAveCharWidth;
LONG tmMaxCharWidth;
[ other structure elds]
}
To use the GetTextMetrics function a structure variable tm should be dened.
TEXTMETRIC tm;

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 33

To determine the text metrics you get a handle to a device context and call GetTextMetrics
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc , &tm);
ReleaseDC (hwnd, hdc);
The most important value in TEXTMETRIC is the tmHeight which is the sum of tmAscent and tmDe-
scent. These two values represent the maximum vertical extents of characters in the font above and below
base line. The term leading refers to the space that the printer inserts between the lines of text. In the
TEXTMETRIC structure internal leading is the space in which accent marks appear and the external leading
is not included in the tmHeight value. It is an amount of space that the designer of the font suggests be added
between successive rows of displayed text. The TEXTMETRIC structure contains two elds that describes
the character width one is tmAveCharWidth eld which is a weighted average of lowercase characters and
another is tmMaxCharWidth which is the width of the widest character in the font.

17 2.8 System Metrics


Display elements are the parts of a window and the display that appear on the system display screen. System
metrics are the dimensions of various display elements. Typical system metrics include the window border
width, icon height, and so on. System metrics also describe other aspects of the system, such as whether a
mouse is installed, double-byte characters are supported, or a debugging version of the operating system is
installed. The header le SYSMETS.H responds to GetSystemMetrics function call. The GetSystemMetrics
function retrieves the specied system metric. If the function succeeds, the return value is the requested
system metric or conguration setting. If the function fails, the return value is zero. System metrics may
vary from display to display. Applications can also retrieve and set the color of window elements such as
menus, scroll bars, and buttons by using the GetSysColor and SetSysColor functions, respectively.
GetSystemMetrics
The GetSystemMetrics function retrieves various system metrics (widths and heights of display elements)
and system conguration settings. All dimensions retrieved by GetSystemMetrics are in pixels.
int GetSystemMetrics ( int nIndex)
The nIndex parameter can be one of the following values. Note that all SM_CX* values are widths and
all SM_CY* values are heights.
Table 2.8 (a) nIndex parameter values

Value Meaning

SM_ARRANGE Flags specifying how the system arranged mini-


mized windows. For more information about mini-
mized windows, see the following Remarks section.

SM_CLEANBOOT Value that species how the system was started:


0 Normal boot1 Fail-safe boot2 Fail-safe with net-
work bootFail-safe boot (also called SafeBoot, Safe
Mode, or Clean Boot) bypasses the user's startup
les.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 34

SM_CMONITORS Windows 98/Me, Windows 2000/XP: Number of


display monitors on the desktop.

SM_CMOUSEBUTTONS Number of buttons on mouse, or zero if no mouse


is installed.

SM_CXBORDER, SM_CYBORDER Width and height of a window border, in pixels.


This is equivalent to the SM_CXEDGE value for
windows with the 3-D look.

SM_CXCURSOR, SM_CYCURSOR Width and height of a cursor, in pixels. The system


cannot create cursors of other sizes.

SM_CXDLGFRAME, SM_CYDLGFRAME Same as SM_CXFIXEDFRAME and


SM_CYFIXEDFRAME.

SM_CXDOUBLECLK, SM_CYDOUBLECLK Width and height of the rectangle around the lo-
cation of a rst click in a double-click sequence,
in pixels. The second click must occur within this
rectangle for the system to consider the two clicks a
double-click. (The two clicks must also occur within
a specied time.) To set the width and height
of the double-click rectangle, call SystemParame-
tersInfo with the SPI_SETDOUBLECLKHEIGHT
and SPI_SETDOUBLECLKWIDTH ags.

SM_CXDRAG, SM_CYDRAG Width and height of a rectangle centered on a drag


point to allow for limited movement of the mouse
pointer before a drag operation begins. These val-
ues are in pixels. It allows the user to click and
release the mouse button easily without uninten-
tionally starting a drag operation.

SM_CXEDGE, SM_CYEDGE Dimensions of a 3-D border, in pixels. These


are the 3-D counterparts of SM_CXBORDER and
SM_CYBORDER.

SM_CXFIXEDFRAME, SM_CYFIXEDFRAME Thickness of the frame around the perimeter of a


window that has a caption but is not sizable, in
pixels. SM_CXFIXEDFRAME is the height of
the horizontal border and SM_CYFIXEDFRAME
is the width of the vertical border. Same as
SM_CXDLGFRAME and SM_CYDLGFRAME.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 35

SM_CXFOCUSBORDER, Windows XP: Width of the left and right edges and
SM_CYFOCUSBORDER the height of the top and bottom edges of the focus
rectangle drawn by DrawFocusRec. These values
are in pixels.

SM_CXFRAME, SM_CYFRAME Same as SM_CXSIZEFRAME and


SM_CYSIZEFRAME.

SM_CXFULLSCREEN, SM_CYFULLSCREEN Width and height of the client area for a full-screen
window on the primary display monitor, in pixels.
To get the coordinates of the portion of the screen
not obscured by the system taskbar or by appli-
cation desktop toolbars, call the SystemParame-
tersInfo function with the SPI_GETWORKAREA
value.

SM_CXHSCROLL, SM_CYHSCROLL Width of the arrow bitmap on a horizontal scroll


bar, in pixels; and height of a horizontal scroll bar,
in pixels.

SM_CXHTHUMB Width of the thumb box in a horizontal scroll bar,


in pixels.

SM_CXICON, SM_CYICON Default width and height of an icon, in pixels. The


LoadIcon function can load only icons of these di-
mensions.

SM_CXICONSPACING, SM_CYICONSPACING Dimensions of a grid cell for items in large icon view,
in pixels. Each item ts into a rectangle of this size
when arranged. These values are always greater
than or equal to SM_CXICON and SM_CYICON.

SM_CXMAXIMIZED, SM_CYMAXIMIZED Default dimensions, in pixels, of a maximized top-


level window on the primary display monitor.

SM_CXMAXTRACK, SM_CYMAXTRACK Default maximum dimensions of a window that has


a caption and sizing borders, in pixels. This met-
ric refers to the entire desktop. The user cannot
drag the window frame to a size larger than these
dimensions. A window can override these values by
processing the WM_GETMINMAXINFO message.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 36

SM_CXMENUCHECK, SM_CYMENUCHECK Dimensions of the default menu check-mark


bitmap, in pixels.

SM_CXMENUSIZE, SM_CYMENUSIZE Dimensions of menu bar buttons, such as the child


window close button used in the multiple document
interface, in pixels.

SM_CXMIN, SM_CYMIN Minimum width and height of a window, in pixels.

SM_CXMINIMIZED, SM_CYMINIMIZED Dimensions of a minimized window, in pixels.

SM_CXMINSPACING SM_CYMINSPACING Dimensions of a grid cell for a minimized window, in


pixels. Each minimized window ts into a rectangle
this size when arranged. These values are always
greater than or equal to SM_CXMINIMIZED and
SM_CYMINIMIZED.

SM_CXMINTRACK, SM_CYMINTRACK Minimum tracking width and height of a window,


in pixels. The user cannot drag the window frame
to a size smaller than these dimensions. A win-
dow can override these values by processing the
WM_GETMINMAXINFO message.

SM_CXSCREEN, SM_CYSCREEN Width and height of the screen of the primary dis-
play monitor, in pixels. These are the same values
obtained by calling GetDeviceCaps (hdcPrimary-
Monitor, HORZRES/VERTRES).

SM_CXSIZE, SM_CYSIZE Width and height of a button in a window's caption


or title bar, in pixels.

SM_CXSIZEFRAME, SM_CYSIZEFRAME Thickness of the sizing border around the perime-


ter of a window that can be resized, in pixels.
SM_CXSIZEFRAME is the width of the horizon-
tal border, and SM_CYSIZEFRAME is the height
of the vertical border. Same as SM_CXFRAME
and SM_CYFRAME.

SM_CXSMICON, SM_CYSMICON Recommended dimensions of a small icon, in pix-


els. Small icons typically appear in window captions
and in small icon view.

SM_CXSMSIZE SM_CYSMSIZE Dimensions of small caption buttons, in pixels.

SM_CXVIRTUALSCREEN, Windows 98/Me, Windows 2000/XP: Width and


SM_CYVIRTUALSCREEN height of the virtual screen, in pixels. The vir-
tual screen is the bounding rectangle of all dis-
play monitors. The SM_XVIRTUALSCREEN,
SM_YVIRTUALSCREEN metrics are the coordi-
nates of the top-left corner of the virtual screen.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 37

SM_CXVSCROLL, SM_CYVSCROLL Width of a vertical scroll bar, in pixels; and height


of the arrow bitmap on a vertical scroll bar, in pix-
els.

SM_CYCAPTION Height of a caption area, in pixels.

SM_CYMENU Height of a single-line menu bar, in pixels.

SM_CYSMCAPTION Height of a small caption, in pixels.

SM_CYVTHUMB Height of the thumb box in a vertical scroll bar, in


pixels.

SM_DBCSENABLED TRUE or nonzero if the double-byte character-set


(DBCS) version of User.exe is installed; FALSE or
zero otherwise.

SM_DEBUG TRUE or nonzero if the debug version of User.exe


is installed; FALSE or zero otherwise.

SM_IMMENABLED Windows 2000/XP: TRUE or nonzero if In-


put Method Manager/Input Method Editor fea-
tures are enabled; FALSE or zero otherwise.
SM_IMMENABLED indicates whether the system
is ready to use a Unicode-based IME on a Unicode
application. To ensure that a language-dependent
IME works, check SM_DBCSENABLED and the
system ANSI code page. Otherwise the ANSI-to-
Unicode conversion may not be performed correctly,
or some components like fonts or registry setting
may not be present.

SM_MENUDROPALIGNMENT TRUE or nonzero if drop-down menus are right-


aligned with the corresponding menu-bar item;
FALSE or zero if the menus are left-aligned.

SM_MIDEASTENABLED TRUE if the system is enabled for Hebrew and Ara-


bic languages.

SM_MOUSEPRESENT TRUE or nonzero if a mouse is installed; FALSE or


zero otherwise.

SM_MOUSEWHEELPRESENT Windows NT 4.0 and later, Windows


98/Me: TRUE or nonzero if a mouse with a
wheel is installed; FALSE or zero otherwise.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 38

SM_NETWORK Least signicant bit is set if a network is present;


otherwise, it is cleared. The other bits are reserved
for future use.

SM_PENWINDOWS TRUE or nonzero if the Microsoft Windows for Pen


computing extensions are installed; FALSE or zero
otherwise.

SM_REMOTECONTROL Windows XP: This system metric is used in a Ter-


minal Services environment. Its value is TRUE if
the current session is remotely controlled; FALSE
otherwise.

SM_REMOTESESSION Windows NT 4.0: This system metric is used in a


Terminal Services environment. If the calling pro-
cess is associated with a Terminal Services client
session, the return value is TRUE or nonzero. If
the calling process is associated with the Terminal
Server console session, the return value is zero.

SM_SECURE TRUE if security is present; FALSE otherwise.

SM_SAMEDISPLAYFORMAT Windows 98/Me, Windows 2000/XP: TRUE if all


the display monitors have the same color format,
FALSE otherwise. Note that two displays can have
the same bit depth, but dierent color formats. For
example, the red, green, and blue pixels can be en-
coded with dierent numbers of bits, or those bits
can be located in dierent places in a pixel's color
value.

SM_SHOWSOUNDS TRUE or nonzero if the user requires an application


to present information visually in situations where
it would otherwise present the information only in
audible form; FALSE, or zero, otherwise.

SM_SHUTTINGDOWN Windows XP: TRUE if the current session is shut-


ting down; FALSE otherwise.

SM_SLOWMACHINE TRUE if the computer has a low-end (slow) proces-


sor; FALSE otherwise.

SM_SWAPBUTTON TRUE or nonzero if the meanings of the left and


right mouse buttons are swapped; FALSE or zero
otherwise.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 39

SM_XVIRTUALSCREEN, Windows 98/Me, Windows 2000/XP: Co-


SM_YVIRTUALSCREEN ordinates for the left side and the top of
the virtual screen. The virtual screen is
the bounding rectangle of all display mon-
itors. The SM_CXVIRTUALSCREEN,
SM_CYVIRTUALSCREEN metrics are the
width and height of the virtual screen.

Table 6

GetSystemMetrics(SM_CMONITORS) counts only display monitors. The SM_ARRANGE setting


species how the system arranges minimized windows, and consists of a starting position and a direction.
The starting position can be one of the following values.
Table 2.8 (b) Starting position values and direction of screen

Value Meaning

ARW_BOTTOMLEFT Start at the lower-left corner of the screen (default


position).

ARW_BOTTOMRIGHT Start at the lower-right corner of the screen. Equiv-


alent to ARW_STARTRIGHT.

ARW_HIDE Hide minimized windows by moving them o the


visible area of the screen.

ARW_TOPLEFT Start at the upper-left corner of the screen. Equiv-


alent to ARV_STARTTOP.

ARW_TOPRIGHT Start at the upper-right corner of the


screen. Equivalent to ARW_STARTTOP |
SRW_STARTRIGHT.

Table 7

Table 2.8 (c) Lists the values of the direction in which to arrange the window.

Value Meaning

ARW_DOWN Arrange vertically, top to bottom.

ARW_LEFT Arrange horizontally, left to right.

ARW_RIGHT Arrange horizontally, right to left.

ARW_UP Arrange vertically, bottom to top.

Table 8

GetSysColor
The GetSysColor function retrieves the current color of the specied display element. Display elements
are the parts of a window and the display that appear on the system display screen. The function returns
the red, green, blue (RGB) color value of the given element. The parameter nIndex is used to retrieve the
color and can have one of the values listed in the Table 2.8(d). If the nIndex parameter is out of range,
the return value is zero. Because zero is also a valid RGB value, you cannot use GetSysColor to determine

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 40

whether a system color is supported by the current platform. Instead, use the GetSysColorBrush function,
which returns NULL if the color is not supported.
DWORD GetSysColor ( int nIndex);
Table 2.8 (d) Color values for GetSysColor function call

Value Meaning

COLOR_3DDKSHADOW Dark shadow for three-dimensional display ele-


ments.

COLOR_3DFACE, COLOR_BTNFACE Face color for three-dimensional display elements


and for dialog box backgrounds.

COLOR_3DHILIGHT, Highlight color for three-dimensional display ele-


COLOR_3DHIGHLIGHT, ments (for edges facing the light source.)
COLOR_BTNHILIGHT,
COLOR_BTNHIGHLIGHT

COLOR_3DLIGHT Light color for three-dimensional display elements


(for edges facing the light source.)

COLOR_3DSHADOW, COLOR_BTNSHADOW Shadow color for three-dimensional display ele-


ments (for edges facing away from the light source).

COLOR_ACTIVEBORDER Active window border.

COLOR_ACTIVECAPTION Active window title bar. Windows 98/Me, Win-


dows 2000/XP: Species the left side color in the
color gradient of an active window's title bar if the
gradient eect is enabled.

COLOR_APPWORKSPACE Background color of multiple document interface


(MDI) applications.

COLOR_BACKGROUND, COLOR_DESKTOP Desktop.

COLOR_BTNTEXT Text on push buttons.

COLOR_CAPTIONTEXT Text in caption, size box, and scroll bar arrow box.

COLOR_GRADIENTACTIVECAPTION Windows 98/Me, Windows 2000/XP: Right


side color in the color gradient of an active win-
dow's title bar. COLOR_ACTIVECAPTION
species the left side color. Use
SPI_GETGRADIENTCAPTIONS with the
SystemParametersInfo function to determine
whether the gradient eect is enabled.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 41

COLOR_GRADIENTINACTIVECAPTION Windows 98/Me, Windows 2000/XP: Right side


color in the color gradient of an inactive window's
title bar. COLOR_INACTIVECAPTION species
the left side color.

COLOR_GRAYTEXT Grayed (disabled) text. This color is set to 0 if the


current display driver does not support a solid gray
color.

COLOR_HIGHLIGHT Item(s) selected in a control.

COLOR_HIGHLIGHTTEXT Text of item(s) selected in a control.

COLOR_HOTLIGHT Windows 98/Me, Windows 2000/XP: Color for a


hot-tracked item. Single clicking a hot-tracked item
executes the item.

COLOR_INACTIVEBORDER Inactive window border.

COLOR_INACTIVECAPTION Inactive window caption. Windows 98/Me, Win-


dows 2000/XP: Species the left side color in the
color gradient of an inactive window's title bar if
the gradient eect is enabled.

COLOR_INACTIVECAPTIONTEXT Color of text in an inactive caption.

COLOR_INFOBK Background color for tooltip controls.

COLOR_INFOTEXT Text color for tooltip controls.

COLOR_MENU Menu background.

COLOR_MENUHILIGHT Windows XP: The color used to highlight


menu items when the menu appears as a at
menu. The highlighted menu item is outlined with
COLOR_HIGHLIGHT.

COLOR_MENUBAR Windows XP: The background color for the menu


bar when menus appear as at menus. However,
COLOR_MENU continues to specify the back-
ground color of the menu popup.

COLOR_MENUTEXT Text in menus.

COLOR_SCROLLBAR Scroll bar gray area.

COLOR_WINDOW Window background.

COLOR_WINDOWFRAME Window frame.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 42

COLOR_WINDOWTEXT Text in windows.

Table 9

SetSysColors
The SetSysColors function sets the colors for one or more display elements. Display elements are the
various parts of a window and the display that appear on the system display screen.
BOOL SetSysColors ( int cElements , const INT* lpaElements, const COLOREF* lpargbvalues);
The rst parameter cElements indicates the number of display elements in the lpaElements array. The
second parameter is a pointer to an array of integers that specify the display elements to be changed. The
third parameter is a pointer to an array of COLORREF values that contain the new red, green, blue (RGB)
color values for the display elements in the array pointed to by the lpaElements parameter.
If the function succeeds, the return value is a nonzero value. If the function fails, the return value is
zero. The SetSysColors function sends a WM_SYSCOLORCHANGE message to all windows to inform
them of the change in color. It also directs the system to repaint the aected portions of all currently visible
windows. The SetSysColors function changes the current session only. The new colors are not saved when
the system terminates
2.9 Client area
The client area is the portion of a window where the application displays output, such as text or graphics
also called a client rectangle. Knowing the size of window's client area the user can display the text within
the client area if the client area is not large enough to hold everything. The dimensions of the client
area is available from the GetSystemMetrics call (SM_CXFULLSCREEN and CY_FULLSCREEN). The
GetClientRect function can be used to determine the dimensions of the client area. A better method in
determining the size of the client area is to process the WM_SIZE message whenever there is a change in
window size. The lparam variable passed to the window procedure contains the width of the client area in
the low word and the height in the high word. For this two static variable has to be dened in the window
procedure as follows:
static int cxClient, cyClient ;
These two variables are set static because they are set while processing one message and used while
processing another message. The WM_SIZE message can be dened as:
case WM_SIZE :
cxClient = LOWORD (lparam);
cyClient = HIWORD (lparam);
return 0;
The number of full lines of text displayable within the client area can be calculated using the formula :
cyClient / cyChar
This is zero if the height of the client area is too small to display a full character. Similarly the approximate
number of lowercase characters that can be displayed horizontally within the client area is equal to
cxClient / cxChar
2.10 GDI Primitives
The types of graphics displayed on the screen can themselves be divided in to several categories, which
are called primitives. These are:

• Bitmaps: A bitmap is an array of bits that represent the attributes of the individual pixels in an image
(1 bit per pixel in a black-and-white display, multiple bits per pixel in a color or grayscale display).
This is used to display complex images on the monitor or printer. Bitmaps are also used to display
small images such as icons, mouse cursors and buttons that appear in the toolbar.

• Text: A Win32 macro that exists so that code can be compiled either as American National Standards
Institute (ANSI) text or as Unicode. For Windows, which supports only Unicode, the macro forces
the compiler to convert ANSI characters to Unicode characters. For example, passing the ANSI

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 43

string "Hello Windows  through the TEXT macro converts all characters in the string to 16-bit
wide characters.

• Lines and Curves: A line is a set of highlighted pixels on a video display (or a series of dots on a printed
page) that is dened by two points: a starting point and an ending point. GDI supports straight lines,
rectangles, ellipses, arcs that are partial curves on the ellipse and Bezier splines. Dierent type of curve
can be drawn as a polyline which is a series of very short lines that dene curve. Furthermore GDI
draws lines using pen selected in the device context.

• Filled areas: To sketch or ll in areas of a drawing with the color and pattern, brush is the tool used.
Paint programs that oer a variety of brush shapes can produce brushstrokes of varying width and, in
some cases, shadowing or calligraphic eects. A brush can be solid color, a pattern (which can be a
series of horizontal, vertical or diagonal hatch marks) or a bitmapped image that is repeated vertically
or horizontally within the area.

2.11 Drawing Point, Line and Curve


Windows can draw straight lines, curved lines and Bezier splines through the following functions:

• SetPixelDraws a single point


• MoveToSets the current position in preparation for drawing
• LineToDraws a line from the current position to the end of the line
• PolylineConnects a set of points with line segments
• PolylineToConnects a set of points with line segments beginning with the

current position and moves the current position to the end of the
polyline

• ArcDraws an arc ArcTo draws an arc and moves the current position

to the end of the arc

• PolyBezierDraws one or more Bezier splines

• PolyBezierToDraws one or more Bezier splines and moves the current position

to the end of the nal spline

• PolyDrawDraws a series of line segments and Bezier splines through a set

points and moves the current position to the end of the nal line segment or spline
The functions that draw lines but that also ll the enclosed area within the gure they draw are as
follows:

• ChordDraws a closed gure bounded by the intersection of an ellipse

and a line

• EllipseDraws a circle or an ellipse


• PieDraws a pie shaped wedge
• PolygonConnects a set of points to form a polygon
• RectangleDraws a rectangle with square corners
• RoundRectDraws a rectangle with rounded corners

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 44

Default line color is black and ll color is white. To draw straight line you must call two functions. The rst
function species the point at which the line begins and the second function species the end point of the
line:
In Windows 3.x, the x- and y-coordinates are 16 bits each and are packed into the 32-bit (DWORD)
function return value, the largest valid size. In Win32, the coordinates are 32 bits each, totaling 64 bits,
and are thus too large to t into a single return value. Each Windows 3.x function is replaced by a Win32
function with the same name, but with an Ex sux added. The Ex functions pass the x- and y-coordinates
using an additional parameter instead of a return value. Both Win32 and Windows 3.x support these new
functions. Each Ex function includes an additional parameter that points to a location to receive data. After
the function call, this data provides the same information as the corresponding function's return value. If
you do not need this information, you can pass NULL to this parameter.
Under Windows 3.x, a call to the MoveTo function can be written as follows:
MoveTo( hDC, x, y );
In the portable version supported by both versions of Windows, the call to MoveTo is rewritten as follows.
Note that the information returned by MoveToEx is ignored:
MoveToEx ( hDC, x, y, NULL );
As a general rule, pass NULL as the last parameter unless you need to use the x- and y-coordinates
returned by the Windows 3.x version.
2.12 Using Stock Pens
The pen determines the lines color, width and style which can be solid, dotted or dashed. The default
pen is BLACK_PEN which draws a solid black line. Apart from BLACK_PEN windows provides other
two pens such as WHITE_PEN and NULL_PEN. NULL_PEN is the pen that doesn't draw. You can also
create your own customized pens. In windows program pen can be referred using a handle. The type HPEN
is a handle to pen. You can dene a variable for using this type denition:
HPEN hpen;
The GetStockObject function call is used to obtain the handle to one of the stock pens. For example if
you want to use the stock pen called BLACK_PEN you can dene the handle like this:
hpen = GetStockObject (BLACK_PEN)
To select that pen in to Device Context use the denition:
SelectObject (hdc,hpen);
Now the BLACK_PEN is the current pen. After this call any line you draw will use the BLACK_PEN
until you select another pen or release the device context handle. Instead of dening hpen variable explicitly
you can combine the StockObject and SelectObject call in to one statement:
SelectObject (hdc, GetStockObject (BLACK_PEN));
If you want to use the WHITE_PEN then you can get that handle to that stock object and select in to
the device context in one statement:
SelectObject (hdc , GetStockObject (WHITE_PEN));
2.13 Creating, Selecting and Deleting Pens
Apart from solid BLACK_PEN and WHITE_PEN you can create your own pens using CreatePen
function call. You can select the pen in to the device context by calling the SelectObject and then draw lines
using new pen. After releasing the device context you can delete the pen by calling DeleteObject. After
doing so the pen is no longer valid. The syntax for CreatePen looks like this:
hpen = CreatePen ( iPenStyle , iWidth, crColor);
The iPenStyle argument determines whether the pen draws a solid line or line with dash and dots. The
argument may be any one of the pen styles listed in gure 2.13.
PS_SOLID____________________________
PS_DASH
PS_DOT. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .. . .
PS_DASHDOT-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
PS_NULL
PS_INSIDEFRAME____________________

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 45

Figure 2.13 Pen Styles


The iWidth argument is the width of the pen. If the value of iWidth argument is zero then Windows
can use one pixel for the pen width. The stock pens are one pixel wide. The crColor argument species the
color of the pen. The PS_INSIDEFRAME is the only pen style which uses dithered color only when the
width is greater than 1. For example if your program uses three pens , a black pen of width 3, a red pen
of width1 and a black dotted pen. First you have to dene static variables for storing the handles to these
pens:
Static HPEN hpen1 , hpen2 , hpen3;
During processing of WM_CREATE you can create the three pens:
hpen1 = CreatePen (PS_SOLID,3,0);
hpen2 = CreatePen (PS_SOLID,1,RGB(255,0,0));
hpen3 = CreatePen(PS_DOT,0,0);
During processing of WM_PAINT message you can select one of these pens in to the device context and
draw with it:
SelectObject (hdc,hpen2)
[ line drawing functions ]
SelectObject(hdc,hpen1);
[line drawing functions]
You can delete the pens by processing WM_DESTROY message:
DeleteObject(hpen1);
DeleteObject(hpen2);
DeleteObject(hpen3);
You can also combine the CreatePen and SelectObject calls in the same statement:
SelectObject (hdc,CreatePen(PS_DASH,0,RGB(255,0,0));
When you draw lines you will be using red dashed pens by executing the above command. Furthermore
the coloring of the gaps between the dashes and the dots needs two attributes such as the background mode
and the background color. The default background mode is opaque which uses the default background color
white. You can also change the background mode to be transparent which prevents the windows from lling
in the gaps by using the command:
SetBkMode (hdc,TRANSPARENT) ;
The current background mode can be obtained by calling GetBkMode. Similarly the background color
can be changed using the command:
SetBkColor (hdc,crColor);
The current background color can be obtained by calling the GetBkColor function.
Example program using pen styles in drawing shapes
Create an application named GraphicsDemo by selecting the project type Win 32 Application in the
appwizard and click OK. Now an empty project without using MFC classes is created. Click File->New and
then select the option C++ Source File and give a name to the .cpp implementation le (here the name is
Graph.cpp). Enter the code given below in the implementation le (Graph.cpp).
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 46

wc.hCursor = LoadCursor(NULL, IDC_ARROW);


wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Graphics Demo Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
In this application Pen style is used to draw shapes. Compile, Build and Execute the program. You will
get dierent shapes in the output window as shown in gure 2.13.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 47

Figure 2.13 Running Instance of Graphics Demo Program


2.14 Filling Enclosed Areas
Windows can draw the outline of the gure (Rectangle, Ellipse, RoundRect, Chord, Polygon etc.,) with
the current pen selected as well as with the current background mode and background color. The gure is
lled with the current brush selected. The default brush is the WHITE_BRUSH. Apart from the default
brush windows uses ve more brushes such as: GRAY_BRUSH, LTGRAY_BRUSH, DKGRAY_BRUSH,
BLACK_BRUSH and HOLLOW_BRUSH or NULL_BRUSH. Any one of the brush can be selected as the
same way as you select the stock pen. First you have to dene a variable for the brush handle:
HBRUSH hbrush;
Where HBRUSH is a handle to the brush. You can get any one of the brush, for example the BLACK_BRUSH
by calling the GetStockObject:
hbrush = GetStockObject ( BLACK_BRUSH);
You can then select in to the device context by calling the SelectObject as:
SelectObject(hdc,hbrush);
Now when you draw a Rectangle the interior will be black. To draw the gure without border NULL_PEN
can be used as:
SelectObject (hdc,GetStockObject (NULL_PEN));
To draw the outline of the gure without lling the interior NULL_BRUSH can be used as:
SelectObject(hdc,GetStockObject(NULL_BRUSH));
The interiors of the gures can be lled with the current brush selected in the device context. You can
select the brush in to the device context with the function SelectObject. The function to create a logical
brush is:

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 48

hbrush = CreateSolidBrush (crColor) ;


You can also create a brush with hatch marks made up of horizontal, vertical or diagonal lines. The
function for creating the hatch brush is:
hbrush = CreateHatchBrush (hatchstyle,crColor)
The hatchstyle argument species one of the hatch styles shown below.

• HS_HORIZONTAL: Horizontal Hatch


• HS_VERTICAL: Vertical Hatch
• HS_FDIAGONAL: Upward hatch (left to right) at 45 degrees
• HS_BDIAGONAL: Downward hatch (left to right) at 45 degrees
• HS_CROSS: Horizontal and vertical crosshatch
• HS_DIAGCROSS: Crosshatch at 45 degrees

The crColor argument species the color of the hatch lines. Once you have a handle to the brush you can
select the brush in to the device context using SelectObject:
SelectObject(hdc,hbrush);
You can later delete a created brush with DeleteObject function:
DeleteObject(hbrush);
Example Program for lling the area of shapes
Create an application named FillArea by selecting the project type Win 32 Application in the appwizard
and click OK. Now an empty project without using MFC classes is created. Click File->New and then select
the option C++ Source File and give a name to the .cpp implementation le (here the name is Filling.cpp).
Enter the code given below in the implementation le (Filling.cpp).
#include <windows.h>
const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{HDC hdc;
PAINTSTRUCT ps;
POINT parray[10]={10,70,50,70,50,10,90,10,90,50,30,50,30,90,70,90,70,30,10,30};
switch(msg)
{
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
SelectObject(hdc,GetStockObject(GRAY_BRUSH));
SetPolyFillMode(hdc,ALTERNATE);
Polygon(hdc,parray,10);//rst parameter handle to device context,second CONST POINT //*lpPoints
pointer to polygon's vertices, third count of polygon's vertices
EndPaint(hwnd,&ps);
return 0;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 49

LPSTR lpCmdLine, int nCmdShow)


{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Filled Area",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
In this application brush style is used to ll the area of polygon. Compile, Build and Execute the program
you will get the output as shown in gure 2.14.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 50

Figure 2.14 Running Instance of FillArea Program


2.15 Keyboard Messages
The message that an application receives from windows about the keyboard events shows the dierence
between keystrokes and characters. Keyboard is a collection of keys. Pressing the key and releasing the key
is called as a keystroke. For keystroke combinations that result in displayable characters windows sends both
keystroke and character messages. But some keys such as shift, function keys, cursor movement keys do not
generate characters. For these keys windows generates only keystroke messages.
There are two types of keystrokes such as System keystroke and Nonsystem keystroke. The SYS in
WM_SYSKEYDOWN and WM_SYSKEYUP stands for system and refers to system keystrokes that
are more important to windows than to windows applications. Nonsystem keystroke messages refer to
messages such as WM_KEYDOWN and WM_KEYUP. For all the four keystroke messages (WM_KEYUP,
WM_KEYDOWN, WM_SYSKEYUP, WM_SYSKEYDOWN) wparam is a virtual key code that identies
the key being pressed or released and lparam contains other data pertaining to keystroke.
Virtual Key Codes
The virtual key code identies the key being pressed or released. The virtual key code is stored in
the wparam parameter . The following table shows the symbolic constant names, hexadecimal values, and
keyboard equivalents for the virtual-key codes used by the Windows operating system. The codes are listed
in numeric order in Table 2.15.
Table 2.15 Virtual Key Codes

Symbolic constant Value (Hex) Mouse or keyboard equivalent

VK_LBUTTON 01 Left mouse button

VK_RBUTTON 02 Right mouse button

VK_CANCEL 03 Control-break processing

VK_MBUTTON 04 Middle mouse button (three-button mouse)

 0507 Undened

VK_BACK 08 BACKSPACE key

VK_TAB 09 TAB key

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 51

 0A0B Undened

VK_CLEAR 0C CLEAR key

VK_RETURN 0D ENTER key

 0E0F Undened

VK_SHIFT 10 SHIFT key

VK_CONTROL 11 CTRL key

VK_MENU 12 ALT key

VK_PAUSE 13 PAUSE key

VK_CAPITAL 14 CAPS LOCK key

 1519 Reserved for Kanji systems

 1A Undened

VK_ESCAPE 1B ESC key

 1C1F Reserved for Kanji systems

VK_SPACE 20 SPACEBAR

VK_PRIOR 21 PAGE UP key

VK_NEXT 22 PAGE DOWN key

VK_END 23 END key

VK_HOME 24 HOME key

VK_LEFT 25 LEFT ARROW key

VK_UP 26 UP ARROW key

VK_RIGHT 27 RIGHT ARROW key

VK_DOWN 28 DOWN ARROW key

VK_SELECT 29 SELECT key

2A OEM specic

VK_EXECUTE 2B EXECUTE key

VK_SNAPSHOT 2C PRINT SCREEN key for Windows 3.0 and later

VK_INSERT 2D INS key

VK_DELETE 2E DEL key

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 52

VK_HELP 2F HELP key

VK_0 30 0 key

VK_1 31 1 key

VK_2 32 2 key

VK_3 33 3 key

VK_4 34 4 key

VK_5 35 5 key

VK_6 36 6 key

VK_7 37 7 key

VK_8 38 8 key

VK_9 39 9 key

3A40 Undened

VK_A 41 A key

VK_B 42 B key

VK_C 43 C key

VK_D 44 D key

VK_E 45 E key

VK_F 46 F key

VK_G 47 G key

VK_H 48 H key

VK_I 49 I key

VK_J 4A J key

VK_K 4B K key

VK_L 4C L key

VK_M 4D M key

VK_N 4E N key

VK_O 4F O key

VK_P 50 P key

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 53

VK_Q 51 Q key

VK_R 52 R key

VK_S 53 S key

VK_T 54 T key

VK_U 55 U key

VK_V 56 V key

VK_W 57 W key

VK_X 58 X key

VK_Y 59 Y key

VK_Z 5A Z key

VK_LWIN 5B Left Windows key (Microsoft Natural Keyboard)

VK_RWIN 5C Right Windows key (Microsoft Natural Keyboard)

VK_APPS 5D Applications key (Microsoft Natural Keyboard)

5E5F Undened

VK_NUMPAD0 60 Numeric keypad 0 key

VK_NUMPAD1 61 Numeric keypad 1 key

VK_NUMPAD2 62 Numeric keypad 2 key

VK_NUMPAD3 63 Numeric keypad 3 key

VK_NUMPAD4 64 Numeric keypad 4 key

VK_NUMPAD5 65 Numeric keypad 5 key

VK_NUMPAD6 66 Numeric keypad 6 key

VK_NUMPAD7 67 Numeric keypad 7 key

VK_NUMPAD8 68 Numeric keypad 8 key

VK_NUMPAD9 69 Numeric keypad 9 key

VK_MULTIPLY 6A Multiply key

VK_ADD 6B Add key

VK_SEPARATOR 6C Separator key

VK_SUBTRACT 6D Subtract key

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 54

VK_DECIMAL 6E Decimal key

VK_DIVIDE 6F Divide key

VK_F1 70 F1 key

VK_F2 71 F2 key

VK_F3 72 F3 key

VK_F4 73 F4 key

VK_F5 74 F5 key

VK_F6 75 F6 key

VK_F7 76 F7 key

VK_F8 77 F8 key

VK_F9 78 F9 key

VK_F10 79 F10 key

VK_F11 7A F11 key

VK_F12 7B F12 key

VK_F13 7C F13 key

VK_F14 7D F14 key

VK_F15 7E F15 key

VK_F16 7F F16 key

VK_F17 80H F17 key

VK_F18 81H F18 key

VK_F19 82H F19 key

VK_F20 83H F20 key

VK_F21 84H F21 key

VK_F22 85H F22 key

VK_F23 86H F23 key

VK_F24 87H F24 key

888F Unassigned

VK_NUMLOCK 90 NUM LOCK key

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 55

VK_SCROLL 91 SCROLL LOCK key

Table 10

2.16 Mouse Messages


Windows sends keyboard messages only to the window that has the input focus. But mouse messages
are dierent, a window procedure receives mouse messages whenever the mouse passes over the window or
clicked within the window. There are two types of mouse messages such as client area mouse messages and
Non client area mouse messages. The client area is the portion of a window where the application displays
output, such as text or graphics. Also called a client rectangle. The parts of a window that are not a part
of the client area. A window's nonclient area consists of the border, menu bar, title bar, and scroll bar.
Table 2.16 (a) Client area mouse messages
Button Pressed Released Pressed (second click)
LeftWM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK
MiddleWM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK
RightWM_RBUTTONDOWN WM_RBUTTONUP WM_RBUTTONDBLCLK
Table 2.16 (b) Non Client area mouse messages
Button Pressed Released Pressed (second click)
LeftWM_NCLBUTTONDOWN WM_NCLBUTTONUP WM_NCLBUTTONDBLCLK
Middle WM_NCMBUTTONDOWN WM_NCMBUTTONUP WM_NCMBUTTONDBLCLK
RightWM_NCRBUTTONDOWN WM_NCRBUTTONUP WM_NCRBUTTONDBLCLK
Example program for mouse and keyboard messages
Create an application named MouseKeyMsg by selecting the project type Win 32 Application in the
appwizard and click OK. Now an empty project without using MFC classes is created. Click File->New and
then select the option C++ Source File and give a name to the .cpp implementation le (here the name is
Mouse.cpp). Enter the code given below in the implementation le (Mouse.cpp).
#include <windows.h>
const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{case WM_LBUTTONDOWN:
MessageBox(GetFocus(),"You have pressed left mouse button","About",MB_OK|MB_ICONINFORMATION);
break;
case WM_RBUTTONDOWN:
MessageBox(GetFocus(),"You have pressed right mouse button","About",MB_OK|MB_ICONINFORMATION);
break;
case WM_KEYDOWN:
MessageBox(0,"You have pressed down arrow key","About",MB_OK|MB_ICONINFORMATION);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 56

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,


LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Mouse and Key operations",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Compile, Build and Execute the program. The output of the program is shown in gure 2.16.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 57

Figure 2.16 Running Instance of MouseKeyMsg Program


Exercises 2

1. What is GDI?
2. Dene DC.
3. What is WM_PAINT Message?
4. List the Paint Structure (PAINTSTRUCT) and explain it.
5. Write the syntax of TextOut function.
6. Dene System Metrics.
7. What is Client area and Non Client area.
8. What are the GDI Primitives?
9. List out the Pen and Brush Styles.
10. Write a Windows Program to draw a Bezier Spline.
11. List out the Mouse and Keyboard Messages.
12. Write a Windows Program to draw a Sine Wave.

Chapter 3
Windows Controls and Resources
3.1 Child Window Controls
Windows provides several predened window classes which we can readily use in our own programs. Most
of the time we use them as components of a dialog box so they're usually called child window controls. The
child window controls process their own mouse and keyboard messages and notify the parent window when
their states have changed. They relieve the burden from programmers enormously so you should use them
as much as possible. Controls can be placed on a normal window by using the Create command with various
styles to design them. But in reality you should put them in a dialog box.
Examples of predened window classes are buttons, listbox, checkboxes, radio buttons, edit controls, etc.
In order to use a child window control, you must create it with win.CreateWindow or win.CreateWindowEx.
Note that you don't have to register the window class since it's registered for you by Windows. The class
name parameter MUST be the predened class name. Say, if you want to create a button, you must specify
"button" as the class name in win.CreateWindowEx. The other parameters you must ll in are the parent
window handle and the control ID. The control ID must be unique among the controls. The control ID is
the ID of that control. You use it to dierentiate between the controls.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 58

After the control was created, it will send messages notifying the parent window when its state has
changed. Normally, you create the child windows during win.WM_CREATE message of the parent window.
The child window sends win.WM_COMMAND messages to the parent window with its control ID in the low
word of wParam, the notication code in the high word of wParam, and its window handle in lParam. Each
child window control has dierent notication codes, refer to your Win32 API reference for more information.
The parent window can send commands to the child windows too, by calling win.SendMessage function.
win.SendMessage function sends the specied message with accompanying values in wParam and lParam to
the window specied by the window handle. It's an extremely useful function since it can send messages to
any window provided you know its window handle.
So, after creating the child windows, the parent window must process win. WM_COMMAND messages
to be able to receive notication codes from the child windows. The examples in this chapter uses dialog
box to place various controls.
3.2 Button Class
Buttons are Windows Controls that respond to user clicks. They are created with the CreateWindow or
CreateWindowEx Window function. They can have a variety of styles as shown below:

• BS_AUTOCHECKBOX Same as a check box, except that a check mark appears in the check box
when the user selects the box; the check mark disappears the next time the user selects the box.
• BS_AUTORADIOBUTTON Same as a radio button, except that when the user selects it, the button
automatically highlights itself and removes the selection from any other radio buttons with the same
style in the same group.
• BS_AUTO3STATE Same as a three-state check box, except that the box changes its state when the
user selects it.
• BS_CHECKBOX Creates a small square that has text displayed to its right (unless this style is
combined with the BS_LEFTTEXT style).
• BS_DEFPUSHBUTTON Creates a button that has a heavy black border. The user can select this
button by pressing the ENTER key. This style enables the user to quickly select the most likely option
(the default option).
• BS_GROUPBOX Creates a rectangle in which other buttons can be grouped. Any text associated
with this style is displayed in the rectangle's upper-left corner.
• BS_LEFTTEXT When combined with a radio-button or check-box style, the text appears on the
left side of the radio button or check box.
• BS_PUSHBUTTON Creates a pushbutton that posts a WM_COMMAND message to the owner
window when the user selects the button.
• BS_RADIOBUTTON Creates a small circle that has text displayed to its right (unless this style is
combined with the BS_LEFTTEXT style). Radio buttons are usually used in groups of related but
mutually exclusive choices.
• BS_3STATE Same as a check box, except that the box can be dimmed as well as checked. The
dimmed state typically is used to show that a check box has been disabled.

3.2.1 Communication between Child and Parent Windows


When you click a button with the mouse the child window control sends a WM_COMMAND message
to its parent window. The program traps the WM_COMMAND message and displays the values of wparam
(child window ID and notication code) and lparam (child window handle). The notication code indicates
in more detail what the message means. The possible button notication messages are:
BN_CLICK
BN_DBCLICK
BN_PAINT
BN_KILLFOCUS
BN_HILITE
BN_UNHILITE

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 59

BN_PUSHED
BN_UNPUSHED
BN_DISABLE
BN_SETFOCUS
BN_KILLFOCUS
In addition to the notication messages mentioned above there are also button messages each begins with
letter BM. These messages are used by the window procedure to send messages to the child window control.
The button messages are:
BM_GETCHECK
BM_GETIMAGE
BM_GETSTATE
BM_SETCHECK
BM_SETIMAGE
BM_SETSTYLE
BM_CLICKED
3.2.2 Push Buttons
A small rectangular control that a user can turn on or o. A push button, also known as a command
button, has a raised appearance in its default o state and a depressed appearance when it is turned on.
Push button controls are used to trigger an immediate action without retaining any type of on/o indication.
The rectangle takes up the full height and width of the dimension given in the CreateWindow. There are two
types of push buttons BS_PUSHBUTTON and BS_DEFPUSHBUTTON where DEF stands for default.
An application sends a BM_SETSTATE message to change the highlight state of a button. The highlight
state indicates whether the button is highlighted as if the user had pushed it.
BM_SETSTATE message syntax:
wParam = (WPARAM) fstate; // highlight state
lParam = 0; // not used; must be zero
where fState is the value of wParam and species whether the button is to be highlighted. A value of
TRUE or nonzero highlights the button. A value of FALSE or zero removes any highlighting.
This message always returns zero. Highlighting only aects the appearance of a button. It has no eect
on the check state or a radio button or check box. A button is automatically highlighted when the user
positions the cursor over it and presses and holds the left mouse button. The highlighting is removed when
the user releases the mouse button.
This call causes the button to be depressed:
SendMessage(hwndButton,BM_SETSTATE,1,0);
To return to the normal state the call to be used is:
SendMessage(hwndButton,BM_SETSTATE,0,0);
The hwndButton window handle is the value returned from the CreateWindow call. You can also send a
BM_GETSTATE message to push button. An application sends a BM_GETSTATE message to determine
the state of a button or check box. The value TRUE is returned if the button is depressed and FALSE if it
is not depressed. Most applications do not require this information.
BM_GETSTATE message syntax:
wParam = 0; // not used; must be zero
lParam = 0; // not used; must be zero
The BM_SETCHECK and BM_GETCHECK messages are not used by push button because they do
not retain on/o information.
3.2.3 Check Boxes
An interactive control found in graphical user interfaces. Check boxes are used to enable or disable one
or more features or options from a set. When an option is selected, an X or a check mark appears in the
box. The two most common styles of check box are BS_CHECKBOX and BS_AUTOCHECKBOX. You
can set the check state of the check box with the message BM_SETCHECK.
BM_SETCHECKMESSAGE has two parameters:

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 60

wParam = (WPARAM)fcheck; // check state


lParam = 0; // not used; must be zero
where fCheck is the value of wParam.and species the check state. This parameter can be one of the
values mentioned in Table 3.2.3.
Table 3.2.3 Values for fCheck Parameter

Value Meaning

BST_CHECKED Sets the button state to checked.

BST_INDETERMINATE Sets the button state to grayed, indicating an inde-


terminate state. Use this value only if the button
has the BS_3STATE or BS_AUTO3STATE style.

BST_UNCHECKED Sets the button state to cleared.

Table 11

You can initialize a check box with a check mark by sending BM_SETCHECK message:
SendMessage(hwndButton,BM_SETCHECK,1,0);
For BS_AUTOCHECKBOX style the button control itself toggles the check mark on and o. When the
current state of the button is needed send the control a BM_GETCHECK message:
iCheck = (int) SendMessage(hwndButton,BM_SETCHECK,0,0);
The value of iCheck is TRUE or nonzero if the button is checked and FALSE or 0 if not checked.
3.2.4 Radio Buttons
A small round button with a label next to it. The label may be text, an icon, or a bitmap. Radio buttons,
also known as option buttons, are usually grouped together in a group box, representing a set of related,
but mutually exclusive options. When a user selects an option button or radio button, all other option
buttons in the same group is automatically unselected. The two most common styles of radio buttons are
BS_RADIOBUTTON and BS_AUTORADIOBUTTON. When you receive a WM_COMMAND message
from a radio button you should display its check by sending it a BM_SETCHECK with wparam equal to 1:
SendMessage(hwndButton,BM_SETCHECK,1,0);
For all other radio buttons in the same group you can turn o the checks by sending them BM_SETCHECK
messages with wparam equal to 0:
SendMessage(hwndButton,BM_SETCHECK,0,0);
3.2.5 Group Boxes
The group box which has the BS_GROUPBOX style is a rectangular area within a dialog box in which
you can group together other controls that are semantically related. The controls are grouped by drawing
a rectangular border around them. Any text associated with the group box is displayed in its upper-left
corner. It neither processes mouse or keyboard input nor sends WM_COMMAND message to its parent.
In the program given below dialog box is used to place various controls. The details regarding the dialog
box creation and usage is given in section 3.3.4.
3.2.6 Changing the Button Text and Input Focus
The text in the button can be changed by calling SetWindowText. However, SetWindowText cannot
change the text of a control in another application.
SetWindowText(
HWND hwnd, // handle to window or control
LPCTSTR lpstring // address of string
);

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 61

17.1 The parameters hwnd is a handle to the window or control whose text is to be changed
and lpstring is a pointer to a null-terminated string to be used as the new title or control text.
17.2 You can also obtain the current text of a window by the command:
GetWindowText(
HWND hwnd, // handle to window or control with text
LPTSTR lpstring, // pointer to buer for text
int nMaxCount // maximum number of characters to copy
);

17.3 The parameters hwnd is a handle to the window or control containing the text, lpstring
is a pointer to the buer that will receive the text and nMaxCount species the maximum
number of characters to copy to the buer, including the NULL character. If the text exceeds
this limit, it is truncated.
17.4 The push buttons, check boxes and radio buttons receive the input focus when they
are clicked with the mouse. When the child window control gets the input focus, the parent
window loses it. However the child window control responds only to the spacebar which now
functions like the mouse. When the window switches the input focus from one window (parent)
to another (child), it rst sends WM_KILLFOCUS message to the window losing the input
focus.
17.5 case WM_KILLFOCUS:
17.6 if (hwnd==GetParent ((HWND) wparam))
17.7 SetFocus (hwnd);
17.8 return 0;
17.9 This method prevents the button from responding to the space bar because the button
never gets input focus. A better approach is to get input focus to the button and also include
the facility to move from button to button using Tab key.
17.10 3.2.7 System Colors
The parts of display can be painted using various system colors. GetSysColor and SetSysColor functions are
used to set these colors. The GetSysColor retrieves the current color of the specied display element. Display
elements are the parts of a window and the display that appear on the system display screen. Identiers
dened in the windows header les specify the system color.
GetSysColor(
int nIndex // display element
);
The parameter nIndex species the display element whose color is to be retrieved. This parameter must
be one of the values mentioned in Table 3.2.7
Table 3.2.7 Values for nInex Parameter

Value Meaning

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 62

COLOR_3DDKSHADOW Dark shadow for three-dimensional display ele-


ments.

COLOR_3DFACE, COLOR_BTNFACE Face color for three-dimensional display elements


and for dialog box backgrounds.

COLOR_3DHILIGHT, Highlight color for three-dimensional display ele-


COLOR_3DHIGHLIGHT, ments (for edges facing the light source.)
COLOR_BTNHILIGHT,
COLOR_BTNHIGHLIGHT

COLOR_3DLIGHT Light color for three-dimensional display elements


(for edges facing the light source.)

COLOR_3DSHADOW, COLOR_BTNSHADOW Shadow color for three-dimensional display ele-


ments (for edges facing away from the light source).

COLOR_ACTIVEBORDER Active window border.

COLOR_ACTIVECAPTION Active window title bar.

COLOR_APPWORKSPACE Background color of multiple document interface


(MDI) applications.

COLOR_BACKGROUND, COLOR_DESKTOP Desktop.

COLOR_BTNTEXT Text on push buttons.

COLOR_CAPTIONTEXT Text in caption, size box, and scroll bar arrow box.

COLOR_GRAYTEXT Grayed (disabled) text. This color is set to 0 if the


current display driver does not support a solid gray
color.

COLOR_HIGHLIGHT Item(s) selected in a control.

COLOR_HIGHLIGHTTEXT Text of item(s) selected in a control.

COLOR_INACTIVEBORDER Inactive window border.

COLOR_INACTIVECAPTION Inactive window caption.

COLOR_INACTIVECAPTIONTEXT Color of text in an inactive caption.

COLOR_INFOBK Background color for tooltip controls.

COLOR_INFOTEXT Text color for tooltip controls.

COLOR_MENU Menu background.

COLOR_MENUTEXT Text in menus.

continued on next page

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 63

COLOR_SCROLLBAR Scroll bar gray area.

COLOR_WINDOW Window background.

COLOR_WINDOWFRAME Window frame.

COLOR_WINDOWTEXT Text in windows.

Table 12

The SetSysColors function sets the colors for one or more display elements. Display elements are the
various parts of a window and the display that appear on the system display screen.
WINAPI SetSysColors(
int cElements, // number of elements to change
CONST int *lpaElements, // address of array of elements
CONST COLORREF *lpargbValues // address of array of RGB values
);
3.2.8 List Box Class
The list box is a window that displays a list of character strings. The user selects a string from the list
by tapping it with the stylus. When a string is selected, it appears highlighted. You can use a vertical or
horizontal scroll bar with a list box to scroll lists that are too long for the control window. The list box
automatically hides or shows the scroll bar, as needed.

17.11 Messages
As you may remember from our earlier discussion of the message loop, windows communicate using messages,
you send them to get a control to do something, and when an event occurs on the control it will send you a
notication message back. For the standard controls this notication will be a WM_COMMAND message
as we've already seen with buttons and menus. For the Common Controls which I may get to later, it will
be WM_NOTIFY.
The messages you send are widely varied between each control, and each control has it's own set of
messages. Once in a while the same message will be used for more than one kind of control, but in general
they will only work on the control they are intended for. This is especially annoying with the listbox
and combobox messages (LB_* and CB_*) which although they perform nearly identical tasks, are NOT
interchangeable.On the other hand, generic messages like WM_SETTEXT are supported by almost all
controls. A control is just a window after all.
You can send messages using the SendMessage() API, and use GetDlgItem() to retreive the handle to the
control, or you can use SendDlgItemMessage() which does both steps for you, the results of both methods
are identical.

17.12 Adding Items to list box


The rst thing you'll want to do with a listbox is add items to it.
int index = SendDlgItemMessage(hwnd, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)"Hi there!");
As you can see, this is a pretty simple task. If the listbox has the LBS_SORT style, the new item will
be added in alphabetical order; otherwise it will just be added to the end of the list.
This message returns the index of the new item either way, and we can use this to perform other tasks
on the item, such as associating some data with it. Usually this will be things like a pointer to a struct
containing more information, or maybe an ID that you will use to identify the item, it's up to you.
SendDlgItemMessage(hwnd, IDC_LIST, LB_SETITEMDATA, (WPARAM)index, (LPARAM)nTimes);

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 64

17.13 Notications
The whole purpose of listboxes is to allow the user to select things from a list. Now sometimes we don't care
when exactly they do this, for example with our Remove button, we don't need to know when the selection
changes right away, we just check when the user activates the button.
However, sometimes you want to be able to do something right away, perhaps display dierent or updated
information based on what items are selected. In order to do this we need to handle the notication messages
that the listbox passes to us. In this case, we are interested in LBN_SELCHANGE, which tells us that
the selection has been modied by the user. LBN_SELCHANGE is sent via WM_COMMAND but unlike
handling the WM_COMMAND from buttons or menu's, which are usually only in response to a click, a list
box sends WM_COMMAND for various reasons, and we need a second check to nd out what it's telling
us. The Notication Code is passed as the HIWORD of wParam, the other half of the parameter that gave
us the control ID in the rst place.
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_LIST:
// It's our listbox, check the notication code
switch(HIWORD(wParam))
{
case LBN_SELCHANGE:
// Selection changed, do stu here.
break;
}
break;
// ... other controls
}
break;

17.14 Getting Data from the ListBox


Now that we know the selection has changed, or at the request of the user, we need to get the selection from
the listbox and do something useful with it.
In this example I've used a multiselection list box, so getting the list of selected items is a little trickier. If
it were a single selection listbox, than you could simply send LB_GETCURSEL to retrieve the item index.
First we need to get the number of selected items, so that we can allocate a buer to save the indexes in.
HWND hList = GetDlgItem(hwnd, IDC_LIST);
int count = SendMessage(hList, LB_GETSELCOUNT, 0, 0);
Then we allocate a buer based on the number of items, and send LB_GETSELITEMS to ll in the
array.
int *buf = GlobalAlloc(GPTR, sizeof(int) * count);
SendMessage(hList, LB_GETSELITEMS, (WPARAM)count, (LPARAM)buf );
// ... Do stu with indexes
GlobalFree(buf );
In this example, buf[0] is the rst index, and so on up to buf[count - 1].
One of the things you would likely want to do with this list of indexes, is retreive the data associated
with each item, and do some processing with it. This is just as simple as setting the data was originally, we
just send another message.
int data = SendMessage(hList, LB_GETITEMDATA, (WPARAM)index, 0);
If the data was some other type of value (anything that is 32-bits) you could simply cast to the appropriate
type. For example if you stored HBITMAPs instead of ints...
HBITMAP hData = (HBITMAP)SendMessage(hList, LB_GETITEMDATA, (WPARAM)index, 0);

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 65

Example Program illustrating the use of Controls


Create an application named ControlDemo by selecting the project type Win 32 Application in the
appwizard and click OK. Now an empty project without using MFC classes is created.
Click Insert->Resource from the menu and then select the Dialog option. Design the dialog as shown in
gure 3.2.8(a).

Figure 3.2.8(a) Dialog design for ControlDemo program


Change the ID for the controls as shown below:
Control TypeID
Edit ControlID_CNAME
List BoxID_ITEM
Option button (Cash)ID_CASH
Option button(Cheque)ID_CHEQUE
Select Insert-> resource from the menu and then select the option Menu from it. The menu contains
two options named (Item and Exit). If the Item option is clicked Dialog box containing the controls will be
displayed. If the Exit option is selected from the menu the output window will be closed. Now close your
dialog window and save your design by giving a name to the Script. This will be stored in .rc extension.
Include this le and the resource header le (resource.h) to your project by clicking Project->Add to Project-
>Files. Now select the .rc and resource.h le for your project and click OK. Now the resource is included in
your project workspace.
Click File->New and then select the option C++ Source File and give a name to the .cpp implementation
le (here the name is Control.cpp). Enter the code given below in the implementation le (Control.cpp).
# include <windows.h>
#include "resource.h"
HINSTANCE hInstance;
WNDCLASS wc;
MSG msg;
HWND hwnd;
LRESULT CALLBACK wndproc(HWND hwnd,UINT wm,WPARAM wp,LPARAM lp);
LRESULT CALLBACK item(HWND hDlg,UINT wm,WPARAM wp,LPARAM lp);
int APIENTRY WinMain(HINSTANCE hInst,HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmd-
Show)
{
//TODO :place code here

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 66

if(hPrevInstance==NULL)
{
memset(&wc,0,sizeof(wc));
wc.style=CS_HREDRAW;
wc.lpfnWndProc=wndproc;
wc.hInstance=hInstance;
wc.hCursor=LoadCursor(hInstance,IDC_CROSS);
wc.hIcon=LoadIcon(hInstance,NULL);
wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszClassName="Sample";
wc.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
if(!RegisterClass(&wc))
return false;
}
hwnd=CreateWindow("Sample","Control Demo",WS_OVERLAPPEDWINDOW,10,10,500,500,NULL,NULL,hInst,NUL
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg,NULL,0,0))
DispatchMessage(&msg);
//return 0;
return true;
}
LRESULT CALLBACK wndproc(HWND hwnd,UINT wm,WPARAM wp,LPARAM lp)
{DLGPROC dlgproc;
switch(wm)
{
case WM_COMMAND:
switch(wp)
{
case ID_ITEM:
dlgproc=(DLGPROC)item;
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),hwnd,dlgproc);
return 0;
break;
case ID_EXIT:
DestroyWindow(hwnd);
break;
}
break;
case WM_DESTROY :
PostQuitMessage(0);
break;
}
return(DefWindowProc(hwnd,wm,wp,lp));
}
char itm[5][10]={ "Hard Disk",
"Printer",
"Monitor",
"Scanner",
"Keyboard"};
LRESULT CALLBACK item(HWND hDlg,UINT wm,WPARAM wp,LPARAM lp)

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 67

{static HWND hlist;


char cname[30],optionsel[10],str[100],payment[10];
int i,sel,cash,cheque;
switch(wm)
{
case WM_INITDIALOG:
for(i=0;i<5;i++)
SendDlgItemMessage(hDlg,ID_ITEM,LB_ADDSTRING,0,(LPARAM)(LPCTSTR)itm[i]);
return true;
case WM_COMMAND:
switch(wp)
{
case IDOK:
sel=SendDlgItemMessage(hDlg,ID_ITEM,LB_GETCURSEL,0,0);
SendDlgItemMessage(hDlg,ID_ITEM,LB_GETTEXT,sel,(LPARAM)(LPCTSTR)optionsel);
cash=SendDlgItemMessage(hDlg,ID_CASH,BM_GETCHECK,0,0);
cheque=SendDlgItemMessage(hDlg,ID_CHEQUE,BM_GETCHECK,0,0);
if(cash==BST_CHECKED)
strcpy(payment,"Cash");
else
{if(cheque==BST_CHECKED)
strcpy(payment,"Cheque");
}
GetDlgItemText(hDlg,ID_CNAME,cname,30);
wsprintf(str,"%s is purchased from %s , Payment is by %s",optionsel,cname,payment);
MessageBox(hDlg,str,"Item details",0);
EndDialog(hDlg,true);
return 1;
case IDCANCEL:
EndDialog(hDlg,false);
return 1;
}
break;
}
return 0;
};
Now Compile, Build and Execute the program. The output window appears as shown in gure 3.2.8(b).
Click the Item option from menu. The dialog resource appears.Select any one of the item from the list box
. Enter the Company name and click OK. A message is displayed as shown in gure 3.2.8(b).

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 68

Figure 3.2.8(b) Running Instance of ControlDemo Program

17.15 3.2.9 Edits


One of the most commonly used controls in the windows environment, the EDIT control, is used to allow
the user to enter, modify, copy, etc... text. Windows Notepad is little more than a plain old window with a
big edit control inside it.
Here is the code used to interface with the edit control in this example:
SetDlgItemText(hwnd, IDC_TEXT, "This is a string");
That's all it takes to change the text contained in the control (this can be used for pretty much any
control that has a text value associated with it, STATICs, BUTTONs and so on).
Retrieving the text from the control is easy as well, although slightly more work than setting it...
int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_TEXT));
if(len > 0)
{
int i;
char* buf;
buf = (char*)GlobalAlloc(GPTR, len + 1);
GetDlgItemText(hwnd, IDC_TEXT, buf, len + 1);
//... do stu with text ...
GlobalFree((HANDLE)buf );
}

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 69

First of all, we need to allocate some memory to store the string in, it won't just return us a pointer
to the string already in memory. In order to do this, we rst need to know how much memory to allocate.
There isn't a GetDlgItemTextLength(), but there is a GetWindowTextLength(), so all we need to do it get
the handle to the control yourself using GetDlgItem().
Now that we have the length, we can allocate some memory. Here I've added a check to see if there is
any text to begin with, since most likely you don't want to be working with an empty string... sometimes
you might, but that's up to you. Assuming that there is something there to work with, we call GlobalAlloc()
to allocate some memory. GlobalAlloc() is equivalent to calloc(), if you're used to DOS/UNIX coding. It
allocates some memory, initializes it's contents to 0 and returns a pointer to that memory. There are dierent
ags you can pass as the rst parameter to make it behave dierently for dierent purposes, but this is the
only way I will be using it in this tutorial.
Note that I added 1 to the length in two places, what's up with that? Well, GetWindowTextLength()
returns the number of characters of text the control contains NOT INCLUDING the null terminator. This
means that if we were to allocate a string without adding 1, the text would t, but the null terminator would
overow the memory block, possibly corrupting other data, causing an access violation, or any number of
other bad things. You must be careful when dealing with string sizes in windows, some APIs and messages
expect text lengths to include the null and others don't, always read the docs thoroughly.
Finally we can call GetDlgItemText() to retrieve the contents of the control into the memory buer that
we've just allocated. This call expects the size of the buer INCLUDING the null terminator. The return
value, which we ignored here, is the number of characters copied, NOT including the null terminator.After
we're all done using the text (which we'll get to in a moment), we need to free up the memory that we
allocated so that it doesn't leak out and drip down onto the CPU and short circuit your computer. To
accomplish this, we simply call GlobalFree() and pass in our pointer.
You may be or become aware of a second set of APIs named LocalAlloc(), LocalFree(), etc... which are
legacy APIs from 16-bit windows. In Win32, the Local* and Global* memory functions are identical.

17.15.1 Edits with Numbers


Entering text is all well and ne, but what if you want the user to enter in a number? This is a pretty
common task, and fortunately there is an API to make this simpler, which takes care of all the memory
allocation, as well as converting the string to an integer value.
BOOL bSuccess;
int nTimes = GetDlgItemInt(hwnd, IDC_NUMBER, &bSuccess, FALSE);
GetDlgItemInt() works much like GetDlgItemText(), except that instead of copying the string to a buer,
it converts it internally into an integer and returns the value to you. The third parameter is optional, and
takes a pointer to a BOOL. Since the function returns 0 on failure, there is no way to tell just from that
whether or not the function failed or the user just entered 0. If you are ne with a value of 0 in the event of
an error, then feel free to ignore this parameter.
Another useful feature is the ES_NUMBER style for edit controls, which allows only the characters 0
through 9 to be entered. This is very handy if you only want positive integers, otherwise it's not much good,
since you can't enter any other characters, including - (minus) . (decimel) or , (comma).

17.16 3.2.10 Statics


Like buttons, static controls are largely trivial, but for the sake or being complete I include them here.
Static controls are usually just that, static, meaning they don't change or really do anything else very
special, they're largely for displaying text to the user. However you can make them slightly more useful by
assigning them a unique ID (VC++ assigns a default ID of IDC_STATIC, which is -1 and eectively means
"No ID") and then setting the text at runtime to present dynamic data to the user.
In the example code, I use one to display the data of the item selected in the list box, assuming one and
only one is selected.

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 70

SetDlgItemInt(hwnd, IDC_SHOWCOUNT, data, FALSE);


3.2.11 Scroll Bar Class
In some graphical user interfaces, a vertical or horizontal bar at the side or bottom of a display area that
can be used with a mouse for moving around in that area. Scroll bars often have four active areas: two scroll
arrows for moving line by line, a sliding scroll box for moving to an arbitrary location in the display area,
and the gray areas in the scroll bar for moving in of one-window increments.
You add the window scroll bar by including the identier WS_VSCROLL or WS_HSCROLL or both in
the window style. scroll bar control can have a number of styles to control the orientation and position of
the scroll bar. You specify the styles that you want when you call the CreateWindowEx function to create a
scroll bar control. Some of the styles create a scroll bar control that uses a default width or height. However,
you must always specify the x- and y-coordinates and the other dimensions of the scroll bar. Two commonly
used scroll bar styles are SBS_VERT and SBS_HORZ.
Example Program to change the Color of the Text using Scroll bar
Create an application named ScrollBar by selecting the project type Win 32 Application in the appwizard
and click OK. Now an empty project without using MFC classes is created. Click File->New and then select
the option C++ Source File and give a name to the .cpp implementation le (here the name is Scroll.cpp).
Enter the code given below in the implementation le (Scroll.cpp).
#include<windows.h>
HINSTANCE hinst;
HWND hscroll[3],hwnd1;
int nval[3];
RECT r;
int i1=255,i2=255,i3=255,j;
int key=0;
int h=0;
HBRUSH hbrush;
LRESULT CALLBACK wndproc(HWND hwnd,UINT wm,WPARAM wp,LPARAM lp)
{
HDC hdc;
PAINTSTRUCT ps;
int i;
r.left=0;
r.right=800;
r.top=0;
r.bottom=800;
switch(wm)
{
case WM_COMMAND:
case WM_CREATE:
for(i=0;i<3;i++)
{
hscroll[i]=CreateWindow("scrollbar","",WS_CHILD,10,10+40*i,
130,30,hwnd,NULL,hinst,NULL);
ShowScrollBar(hscroll[i],SB_CTL,SW_SHOW);
SetScrollRange(hscroll[i],SB_CTL,0,255,FALSE);
SetScrollPos(hscroll[i],SB_CTL,0,TRUE);
nval[i]=0;
}
break;
case WM_HSCROLL:
switch(LOWORD(wp))

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 71

{
case SB_LINEUP:
hwnd1=(HWND)lp;
for(j=0;j<3;j++)
{
if(hscroll[j]==hwnd)
break;
}
nval[j]-=1;
h=nval[j];
break;
case SB_LINEDOWN:
hwnd1=(HWND)lp;
for(j=0;j<3;j++)
{
if(hscroll[j]==hwnd1)
break;
}
nval[j]+=1;
h=nval[j];
break;
case SB_PAGEDOWN:
hwnd1=(HWND)lp;
for(j=0;j<3;j++)
{
if(hscroll[j]==hwnd1)
break;
}
nval[j]+=10;
h=nval[j];
break;
case SB_PAGEUP:
hwnd1=(HWND)lp;
for(j=0;j<3;j++)
{
if(hscroll[j]==hwnd1)
break;
}
nval[j]-=10;
h=nval[j];
break;
case SB_THUMBPOSITION:
hwnd1=(HWND)lp;
for(j=0;j<3;j++)
{
if(hscroll[j]==hwnd1)
{
h=HIWORD(wp);
nval[j]=h;
break;
}

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 72

}
break;
}
ShowScrollBar(hwnd1,SB_CTL,SW_SHOW);
SetScrollPos(hwnd1,SB_CTL,h,TRUE);
hdc=GetDC(hwnd);
if(key==0)
{
SetTextColor(hdc,RGB(nval[0],nval[1],nval[2]));
TextOut(hdc,100,200,"the Color of the text is changing",33);
ReleaseDC(hwnd,hdc);
}
else
{
i1=nval[0];
i2=nval[1];
i3=nval[2];
SetClassLong(hwnd,GCL_HBRBACKGROUND,(LONG)CreateSolidBrush(RGB(nval[0],nval[1],nval[2])));
SetBkColor(hdc,RGB(nval[0],nval[1],nval[2]));
InvalidateRect(hwnd,&r,TRUE);
}
break;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,wm,wp,lp);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = wndproc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "scroll bar";

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 73

wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);


if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
"scroll bar",
"Scroll bar Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Compile, Build and Execute the program. The output of the program is shown in gure 3.2.11. As you
scroll the scroll bars the color of the text will be changed.

Figure 3.2.11 Running Instance of ScrollBar Program

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 74

3.3 Windows Resources


Windows resources include icons, cursors, menus, dialog boxes, bitmaps, fonts, keyboard accelerator
tables, message table entries, string table entries, version data, and user-dened data. Resources are data
that are stored in program's .exe le, but they do not reside in the executable program's data area. Windows
provides functions that explicitly or implicitly load a programs resource in to memory so that they can be
used. In this section the resources such as icons, cursors, character strings, menus, keyboard accelerators,
dialog boxes and bitmaps are described.
3.3.1 Icons
An icon is a small bitmap that represents another object in a windows program. Icons are used to
represent minimized child windows in MDI application. Icons are widely used by windows itself. When
a program is minimized its icon is displayed in the windows task bar. When you are using the explorer,
the icon representing an application associated with each le is displayed next to the le's name. Windows
displays the program's icon in the upper left corner of the main window title bar. There are four dierent
types of icons such as:

• Large Icons: Used for most programs written for windows before the release of Windows 95, these
icons are 32x32 pixels in size and support 16 colors.
• Small Icons: First introduced with Windows 95, these icons are usually a smaller 16x16 pixels version
of a program's large icon.
• 256 Color Icons: These icons support more than the standard 16 colors available to other types of
icons. These icons are 48x48 pixels in size and never displayed as a program's icon when the window
is minimized.
• Monochrome Icons: These icons support only two colors and are 32x32 pixels.

Creating Icons Using Image Editor


When creating a new project, AppWizard creates a set of default icons for your project automatically.
You can use the Developer Studio image editor to edit or create new icons for your project. To open the
image editor, open the Resource view in the project workspace and then open the icon folder. Double click
any icon resource contained in the folder to open the editor.
To insert a new icon resource in to an existing project, right click the icon folder in the resource view
and select insert icon from pop up menu; this opens the image editor with a blank icon ready for editing.

Figure 3.3.1 The standard 32x32 Icon le as displayed in Developer Studio
The program can be compiled and run now. Developer studio has put a line in the .rc resource script
that equates the icon le with an identier (IDI_ICON). The header le resource.h contains the denition
of IDI_ICON. Developer studio compiles resources by using the resource compiler rc.exe. The text resource
script is converted in to a binary form which is a le with extension .res.
Loading an Icon in your programs
After you have added an icon to a project, loading and displaying it can be bone through LoadIcon
command. A program can obtain a handle to icon by calling LoadIcon:

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 75

hIcon = LoadIcon (hInstance,MAKEINTRESOURCE (IDI_ICON));

17.16.1 LoadIcon returns a value of type HICON, a handle to an icon. The parameters hIn-
stance is a handle to an instance of the module whose executable le contains the icon to be
loaded. This parameter must be NULL when a standard icon is being loaded and MAKEIN-
TRESOURCE contains the name of the icon resource to be loaded. To use one of the predened
icons, set the hInstance parameter to NULL and the second parameter to one of the values in
Table 3.3.1.
17.16.2 Table 3.3.1 Second Parameter values for LoadIcon

Value Description

IDI_APPLICATION Default application icon.

IDI_ASTERISK Same as IDI_INFORMATION.

IDI_ERROR Hand-shaped icon.

IDI_EXCLAMATION Same as IDI_WARNING.

IDI_HAND Same as IDI_ERROR.

IDI_INFORMATION Asterisk icon.

IDI_QUESTION Question mark icon.

IDI_WARNING Exclamation point icon.

IDI_WINLOGO Windows logo icon.

Table 13

The icon created can be displayed in its client area, repeated horizontally and vertically using the state-
ment LoadIcon and obtains a handle to the icon using the statements:
cxIcon = GetSystemMetrics (SM_CXICON);
cyIcon = GetSystemMetrics (SM_CYICON);
It obtains the size of the icon. The program can then display the icon with multiple calls to
DrawIcon (hdc , x , y ,hIcon);
Where x and y coordinates of where the upper left corner of the displayed icon is positioned. The smaller
icon size can also be obtained from the system metrics SM_CXSMSIZE and SM_CYSMSIZE indices. The
rst SM means system metrics and the second SM means small.
Example program for icon demo
Create an application named IconDemo by selecting the project type Win 32 Application in the appwizard
and click OK. Now an empty project without using MFC classes is created.
Click Insert->Resource from the menu and then select the Icon option. Design the Icon as shown in
gure 3.3.1(a).

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 76

Figure 3.3.1(a) Icon design for the program


Save the icon design in your project and then include the .rc and resource.h header le to your project
workspace. Change the ID for Icon as ID_ICON Click File->New and then select the option C++ Source
File and give a name to the .cpp implementation le (here the name is Icon.cpp). Enter the code given below
in the implementation le (Icon.cpp).
#include <windows.h>
#include "resource.h"
const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{static HICON hIcon;
static int cxIcon,cyIcon,cxClient,cyClient;
HDC hdc;
HINSTANCE hInstance;
PAINTSTRUCT ps;
int x,y;
switch(msg)
{
case WM_CREATE:
hInstance=((LPCREATESTRUCT)lParam)->hInstance;
hIcon=LoadIcon(hInstance,MAKEINTRESOURCE (IDI_ICON));
cxIcon=GetSystemMetrics(SM_CXICON);
cyIcon=GetSystemMetrics(SM_CYICON);
return 0;
case WM_SIZE:
cxClient=LOWORD(lParam);
cyClient=HIWORD(lParam);
return 0;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
for(y=0;y<cyClient;y+=cyIcon)
for(x=0;x<cxClient;x+=cxIcon)
DrawIcon(hdc,x,y,hIcon);
EndPaint(hwnd,&ps);
return 0;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 77

PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Icon Demo Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Compile, Build and Execute the program. The output is as shown in gure 3.3.1(b).

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 78

Figure 3.3.1(b) Running Instance of IconDemo Program


3.3.2 Cursors
Cursors represent the position of a pointing device, such as a mouse. You can create a cursor in the same
way as an icon by selecting resource from insert menu and selecting cursor. After you have added a cursor
to a project, loading and displaying it can be bone through LoadCursor command.
wndclass.hCursor = LoadCursor (hInstance,szCursor);
Whenever the mouse is positioned over a window created based on this class the cursor associated with
IDC_CURSOR or szCursor will be displayed. If you separate your client area in to smaller logical areas
without using child windows, you can use SetCursor to establish the cursor shape.
SetCursor (hCursor);
3.3.3 Menus
A menu is probably the most important of the consistent user interface that windows programs oer, and
adding a menu to your program is a relatively easy part of windows programming. This will be created as
.rc le and will be compiled and linked into your .exe. This is rather compiler specic, commercial compilers
will have a resource editor that you can use to create your menus, but for this example I will show the text
of the .rc le so you can add it in manually. I usually have an .h le as well which is included in both my .rc
le and my .c source les. This le contains the identiers for controls and menu items etc.
For this example you can start with the window code from simple_window and add this code into it as
instructed.
First the .h le. Usually called "resource.h"
#dene IDR_MYMENU 101
#dene IDI_MYICON 201
#dene ID_FILE_EXIT 9001
#dene ID_STUFF_GO 9002
Not much there, but our menu will be pretty simple. The names and values here are up to you for the
choosing. Now we write our .rc le.
#include "resource.h"
IDR_MYMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Stu"
BEGIN
MENUITEM "&Go", ID_STUFF_GO
MENUITEM "G&o somewhere else", 0, GRAYED
END

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 79

END
IDI_MYICON ICON "menu_one.ico"
You will want to add the .rc le to your project or makele depending on what tools you are using.
You also want to #include "resource.h" in your source le (.c) so that the menu command identiers
and the menu resource id will be dened. The easiest way to attach the menu and icon to your window is
to specify them when you register the window class, like this:
wc.lpszMenuName=MAKEINTRESOURCE(IDR_MYMENU); wc.hIcon=LoadIcon(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDI_MYICON));
wc.hIconSm=(HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON),
IMAGE_ICON, 16, 16, 0);
Change that and see what happens. Your window should now have a File and Stu menu with the
respective items underneath. That is assuming your .rc le was properly compiled and linked into your
program.
I've used LoadIcon() to load the large icon because it's simpler, however it will only load icons at the
default resolution of 32x32, so in order to load the smaller image, we need to use LoadImage(). Be aware
that icon les and resources can contain multiple images, and in this case the ones I've supplied contain the
two sizes that I'm loading.
An alternative to using a menu resource is to create one on the y (or when your program runs). This
is a bit more work programming wise, but adds exibility and is sometimes necessary.
You can also use icons that aren't stored as resources, you could choose to store your icon as a separate
le and load it at runtime. This would also give you the option of allowing the user to select an icon of their
choice with the common dialogs discussed later, or something to that eect.
Start again from simple_window without the .h or .rc added. Now we will handle the WM_CREATE
message and add a menu to our window.
#dene ID_FILE_EXIT 9001
#dene ID_STUFF_GO 9002
Put these two id's at the top of your .c le this time, underneath your #includes. Next we add the
following code into our WM_CREATE handler.
case WM_CREATE:
{
HMENU hMenu, hSubMenu;
HICON hIcon, hIconSm;
hMenu = CreateMenu();
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
AppendMenu(hMenu,MF_STRING| MF_POPUP,(UINT)hSubMenu, "&File");
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&Go");
AppendMenu(hMenu,MF_STRING|MF_POPUP, (UINT)hSubMenu, "&Stu");
SetMenu(hwnd, hMenu);
hIcon=LoadImage(NULL,"menu_two.ico",IMAGE_ICON,32,32,LR_LOADFROMFILE);
if(hIcon)
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
else
MessageBox(hwnd,"Could not load large icon!", "Error", MB_OK | MB_ICONERROR);
hIconSm = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
if(hIconSm)
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
else
MessageBox(hwnd, "Could not load small icon!", "Error", MB_OK | MB_ICONERROR);
}

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 80

break;
This creates a menu almost the same as the one we had in the resource and attaches it to our window.
A menu that is assigned to a window is automatically removed when the program terminates, so we don't
need to worry about getting rid of it later. If we did though, we could use GetMenu() and DestroyMenu().
The code for the icons is pretty simple, we call LoadImage() twice, to load the icon as both a 16x16
size and a 32x32 size. We can't use LoadIcon() at all because it will only load resources, not les. We
specify NULL for the instance handle parameter because we aren't loading a resource from our module,
and instead of a resource ID we pass in the name of the icon le we want to load. Finally, we pass in the
LR_LOADFROMFILE ag to indicate that we want the function to treat the string we give it as a lename
and not a resource name.
If each call succeeds we assign the icon handle to our window with WM_SETICON, and if it fails we
pop up a message box letting us know something went wrong. Note that the LoadImage() calls will fail if
the icon le isn't in the current working directory of the program. If you are using VC++ and you run the
program from the IDE, the current working directory will be the one the project le is in. However if you
run the program from the Debug or Release directories from explorer or the command shell, then you'll need
to copy the icon le into that directory in order for the program to nd it. If all else fails, specify the full
path to the icon, "C:\\Path\\To\\Icon.ico".
Now that we have our menu, we need to make it do something. This is pretty simple, all we need to do
is handle the WM_COMMAND message. Also we'll need to check which command we are getting and act
accordingly. Now our WndProc() should look something like this.
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_CREATE:
{
HMENU hMenu, hSubMenu;
hMenu = CreateMenu();
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&File");
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&Go");
AppendMenu(hMenu,MF_STRING|MF_POPUP, (UINT)hSubMenu, "&Stu");
SetMenu(hwnd, hMenu);
hIcon = LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
if(hIcon)
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
Else
MessageBox(hwnd, "Could not load large icon!", "Error", MB_OK | MB_ICONERROR);
hIconSm=LoadImage(NULL,"menu_two.ico",IMAGE_ICON,16,16, LR_LOADFROMFILE);
if(hIconSm)
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
else
MessageBox(hwnd, "Could not load small icon!", "Error", MB_OK | MB_ICONERROR);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 81

break;
case ID_STUFF_GO:
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}
As you can see we've got our WM_COMMAND all set up, and it even has another switch() in it. This
switch()'s on the value of the low word of wParam, which in the case of WM_COMMAND contains the
control or menu id that sent the message.
We obviously want the Exit menu item to close the program. So in the WM_COMMAND, ID_FILE_EXIT
handler you can use the following code to do just that.
PostMessage(hwnd, WM_CLOSE, 0, 0);
Your WM_COMMAND handler should now look like this:
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case ID_STUFF_GO:
break;
}
break;
Example Program to illustrate menu design
Create an application named ModalDialog by selecting the project type Win 32 Application in the
appwizard and click OK. Now an empty project without using MFC classes is created. Design the Menu
resource with the options Stu and File. Under the option Stu options Go and GoSomewhereElse are
included. Under the option File->Exit is included. After designing the menu save the script with .rc
extension and then include this .rc le and resource.h header le in your project. Change the ID for menu
as IDR_MENU1. Similarly open the Icon resource and make a design of your own. Change the ID of Icon
as IDI_MYICON. The Icon which you design will appear on the top of the window.
Click File->New and then select the option C++ Source File and give a name to the .cpp implementation
le (here the name is Menu.cpp). Enter the code given below in the implementation le (Menu.cpp).
#include <windows.h>
#include "resource.h"
const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{switch(Message)
{
case WM_COMMAND:
switch(LOWORD(wParam))

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 82

{
case ID_FILE_EXIT:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case ID_STUFF_GO:
MessageBox(hwnd, "You clicked Go!", "Woo!", MB_OK);
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon=LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
wc.hCursor= LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
wc.lpszClassName = g_szClassName;
wc.hIconSm =(HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON),
IMAGE_ICON, 16, 16, 0);
if(!RegisterClassEx(&wc))
{MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"A Menu",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 83

{MessageBox(NULL, "Window Creation Failed!", "Error!",


MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Compile, Build and Execute the Program. The output is as shown in gures 3.3.3(a) and 3.3.3(b). Click
the menu item Stu. The message is displayed as shown in gure 3.3.3(b)

Figure 3.3.3(a) Running Instance of Menu program

Figure 3.3.3(b) Running Instance of Menu program


3.3.4 Dialog Box

18 A dialog box is a temporary window that contains controls. You can use it
to display status information and to get user input. Just go File -> Open in any
text editor or any other kind of editor; you are presented with a dialog box, one
that probably allows you to select a le to be opened. Dialogs aren't limited to
the standard open le ones; they can look like and do whatever you choose. The
attractive point of dialogs is that they provide a quick way to arrange and create
a GUI (Graphic User Interface) and even some default processing, cutting down
on the amount of code you must write.
One thing to remember is that dialogs are just windows. The dierence between a dialog and a "normal"
window is that the system does some additional default processing for dialogs, such as creating and initializing
controls, and handling tab order. Nearly all APIs that are applicable to "normal" windows will work just
as well on dialogs, and vice versa! There are two types of dialog box such as modal and modeless dialog
box. The modal dialog box is the most common. When your program displays a modal dialog box the user

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 84

must explicitly end the dialog box by clicking a push button marked either OK or Cancel. The user can
switch to another program while the dialog box is still displayed.
The rst step is to create the dialog resource. As with any resource how you do this will depend on your
compiler/IDE. Here I will show you the plain text of the dialog in the .rc le and let you incorporate it into
your project.
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 239, 66
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "My About Box"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&OK",IDOK,174,18,50,14
PUSHBUTTON "&Cancel",IDCANCEL,174,35,50,14
GROUPBOX "About this program...",IDC_STATIC,7,7,225,52
CTEXT "An example program showing how to use Dialog Boxes\r\n\r\n by Avanija",IDC_STATIC,16,18,144,33
END
On this rst line, IDD_ABOUTDLG is the id of the resource. DIALOG is the resource type, and the four
number are the Left, Top, Width and Height co-ordinates. These ARE NOT PIXELS, they are in Dialog
Units, which are based on the size of the font used by the system (and chosen by the user). If you have a
large font selected, the dialog will be large, if you use a smaller font, the dialog will be that much smaller.
This is important as it makes sure that all of the controls are the proper size to display their text in the
current font. You can convert dialog units to pixels at runtime using MapDialogRect(). DISCARDABLE
tells the system it may swap the resource memory to disk when it's not being used in order to conserve
system resources (essentially pointless).
The second line starts with STYLE and follows with the window styles that will be used to create the
dialog. These should be explained under CreateWindow() in your help les. In order to use the predened
constants you may need to add #include "windows.h" to your .rc le, or in the case of VC++, winres.h or
afxres.h will do. If you use the resource editor these les will certainly be included automatically if needed.
The CAPTION line should be self explanatory. The FONT line species the size and name of the font
you wish to use for this dialog box. This might not end up exactly the same on each computer as dierent
people will have dierent fonts and may have specied dierent font sizes. You usually don't need to worry
about that though. Now we have the list of controls to create on the dialog:
DEFPUSHBUTTON "&OK",IDOK,174,18,50,14
Here's the line for the OK button. The & in this case like with menus underlines the next letter "O", so
that by pressing Alt+O the user can activate this control (part of the default processing I mentioned). IDOK
is the control identier. IDOK is pre-dened so we don't need to #dene it ourselves. The four numbers at
the end are the left, top, width and height, all in dialog units.
This information should be purely academic, as you almost always use a resource editor to create dialogs,
but knowing how to do it from text is sometimes necessary, expecially if you have no visual editor.
Two of the controls have an ID of IDC_STATIC (which is -1), this is used to indicate we never need to
access them, so they have no need of an identier. However it doesn't hurt to give them an ID and your
resource editor might do so automatically.
The "\r\n" in the text of the static control is a CR-LF pair, the way windows represents a new line.
So! Having added that to your .rc le we need to write a Dialog Procedure to process message for this box.
Don't worry this is nothing new, it's practicly the same as our main Window Procedure (but not exactly).
BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 85

switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hwnd, IDOK);
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
There are a few important dierences between a dialog procedure and window procedure. One is that
you DO NOT call DefWindowProc() for message you don't handle. With dialogs this is done automatically
for you (and will really screw things up if you do it).
Secondly, in general you return FALSE for messages you don't process, and TRUE for messages you do
process, UNLESS the message species you return something else. Note that this is what we do above, the
default is to do nothing and return FALSE, while messages we do handle break the switch() and return
TRUE.
Thirdly, You do not call DestroyWindow() to close a dialog, you call EndDialog(). The second parameter
is the value that is returned to whatever code called DialogBox().
Finally, instead of handling WM_CREATE, you handle WM_INITDIALOG to do any processing that
needs to be done before the dialog appears, and then return TRUE to have the keyboard focus set to the
default control. (You can actually handle WM_CREATE as well, but it is sent BEFORE any of the controls
have been created, so you can't access them. In WM_INITDIALOG the controls have already been created).
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_HELP_ABOUT:
{
int ret = DialogBox(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
if(ret == IDOK){
MessageBox(hwnd, "Dialog exited with IDOK.", "Notice",
MB_OK | MB_ICONINFORMATION);
}
else if(ret == IDCANCEL){
MessageBox(hwnd, "Dialog exited with IDCANCEL.", "Notice",
MB_OK | MB_ICONINFORMATION);
}
else if(ret == -1){
MessageBox(hwnd, "Dialog failed!", "Error",
MB_OK | MB_ICONINFORMATION);
}
}
break;
// Other menu commands...
}

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 86

break;
This is the code used to create my about box, you can probably guess that this is to be merged into
your WM_COMMAND handler, if you aren't clear on this aspect, you might want to review the section on
menus. ID_HELP_ABOUT is the identier of my Help -> About menu item.
Since we want the menu on our main window to create the dialog, we obviously want to put this code
in the WndProc() of our main window, not the dialog proc. Now the return value is by making a call to
DialogBox(), this is just so you can observe the eects of pressing the two buttons, hitting Esc, Enter etc...
from inside the dialog. It also illustrates how to use the return value from a dialog box to check for success,
failure, a users choice, or whatever other information you choose to send back to the caller from the Dialog
Procedure.
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
This is the only important part, and you can choose to put it wherever in your code that you want the
dialog to come up. IDD_ABOUT is the id of the dialog resource. hwnd is the handle to the parent window
of the dialog. AboutDlgProc() is of course the dialog procedure to use to control the dialog.
A particularly astute reader might eventually wonder, if DialogBox() doesn't return until the dialog closes
we can't process messages while it's up, so how does it work? Well the nifty thing about DialogBox() is that
it has it's own message loop, so while the dialog is displayed, our message loop is out of the picture and the
default loop is handled by windows. This loop also takes care of fun things like moving the keyboard focus
from control to control when you press Tab.
Another eect of using DialogBox is that your main window is disabled until the dialog is dismissed.
Sometimes this is what we want, and sometimes it isn't, such as when we want to use a dialog as a oating
toolbar. In this case we want to be able to interact with both out dialog and our main window.
Example program for Modal dialog box
Create an application named ModalDialog by selecting the project type Win 32 Application in the
appwizard and click OK. Now an empty project without using MFC classes is created. Design the Menu
resource with the options Help and File. Under the option Help->About and under File->Exit are included.
After designing the menu open the dialog resource and design it as shown in gure 3.3.4(a). Next step is
to save the script with .rc extension and then include this .rc le and resource.h header le in your project.
Change the ID for menu as IDR_MYMENU and the ID for dialog as IDD_ABOUT.

Figure 3.3.4(a) Dialog design for ModalDialog Program.


Click File->New and then select the option C++ Source File and give a name to the .cpp implementation
le (here the name is Dialog.cpp). Enter the code given below in the implementation le (Dialog.cpp).
#include <windows.h>
#include "resource.h"
const char g_szClassName[] = "myWindowClass";
BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 87

case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
EndDialog(hwnd, IDOK);
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case ID_HELP_ABOUT:
{
int ret = DialogBox(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
if(ret == IDOK){
MessageBox(hwnd, "Dialog exited with IDOK.", "Notice",MB_OK | MB_ICONINFORMATION);
}
else if(ret == IDCANCEL){
MessageBox(hwnd, "Dialog exited with IDCANCEL.", "Notice",
MB_OK | MB_ICONINFORMATION);
}
else if(ret == -1){
MessageBox(hwnd, "Dialog failed!", "Error",
MB_OK | MB_ICONINFORMATION);
}
}
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 88

PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Compile, Build and Execute the program. The output is shown through gures 3.3.4(b) through 3.3.4(d).

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 89

Figure 3.3.4(b) Running Instance of ModalDialog Program

Figure 3.3.4(c) Running Instance of ModalDialog Program

Figure 3.3.4(d) Running Instance of ModalDialog Program


3.3.5 Modeless Dialogs

Figure 2

Now we take a look at CreateDialog(), DialogBox()'s sister function. The dierence is that while Dialog-
Box() implements it's own message loop and does not return until the dialog is closed, CreateDialog() acts
more like a window created with CreateWindowEx() in that it returns immediately and depends on your
message loop to pump the messages as it does for your main window. This is termed Modeless, whereas
DialogBox() creates Modal dialogs.
You can create the dialog resource just like you did for the last dialog example, you might also want to
set the "Tool window" extended style to give it's title bar the typical smaller caption of toolbars. The dialog
resource is created as follows:
IDD_TOOLBAR DIALOGEX 0, 0, 98, 52
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
EXSTYLE WS_EX_TOOLWINDOW

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 90

CAPTION "My Dialog Toolbar"


FONT 8, "MS Sans Serif"
BEGIN
PUSHBUTTON "&Press This Button",IDC_PRESS,7,7,84,14
PUSHBUTTON "&Or This One",IDC_OTHER,7,31,84,14
END
You may notice that the resource editor has replaced DIALOG with DIALOGEX indicating we want to
set an EXSTYLE on our dialog.
Next we want to create the dialog when our program runs with the help of the command WM_CREATE.
We also want to declare a global variable to hold the window handle returned from CreateDialog() so that
we can use it later. DialogBox() didn't return a handle to us since when DialogBox() returns the window
has been destroyed.
HWND g_hToolbar = NULL;
case WM_CREATE:
g_hToolbar = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_TOOLBAR),
hwnd, ToolDlgProc);
if(g_hToolbar != NULL)
{
ShowWindow(g_hToolbar, SW_SHOW);
}
else
{
MessageBox(hwnd, "CreateDialog returned NULL", "Warning!",
MB_OK | MB_ICONINFORMATION);
}
break;
We show the window with ShowWindow(), with DialogBox() this isn't necessary since the system calls
ShowWindow() for us. Now we need a dialog procedure for our toolbar.
BOOL CALLBACK ToolDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_PRESS:
MessageBox(hwnd, "Hi!", "This is a message",
MB_OK | MB_ICONEXCLAMATION);
break;
case IDC_OTHER:
MessageBox(hwnd, "Bye!", "This is also a message",
MB_OK | MB_ICONEXCLAMATION);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 91

Most of the same message handling rules apply to dialogs created with CreateDialog() as with Dialog-
Box(), don't call DefWindowProc(), return FALSE for messages you don't handle and TRUE for those you
do.
One change is that we don't call EndDialog() for modeless dialogs, we can use DestroyWindow() just
like for regular windows. In this case I destroy the dialog when the main window is destroyed. In the main
window's WndProc()...
case WM_DESTROY:
DestroyWindow(g_hToolbar);
PostQuitMessage(0);
break;
Last but not least, we want to be able to display and hide our toolbar whenever we choose so I've added
two commands to my menu to do this, and handled them so:
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_DIALOG_SHOW:
ShowWindow(g_hToolbar, SW_SHOW);
break;
case ID_DIALOG_HIDE:
ShowWindow(g_hToolbar, SW_HIDE);
break;
//... other command handlers
}
break;
You should be able to create your own menu using the resource editor or manually.Now when you run
the program, you should be able to access both the dialog window, and main window at the same time.
If you've run the program at this point and tried tabbing between the two buttons, you have probably
noticed it doesn't work, neither does hitting Alt-P or Alt-O to activate the buttons. Why not? Whereas
DialogBox() implements it's own message loop and handles these events by default, CreateDialog() does not.
We can do it ourselves though, by calling IsDialogMessage() in our message loop which will do the default
processing for us.
while(GetMessage(&Msg, NULL, 0, 0))
{
if(!IsDialogMessage(g_hToolbar, &Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
Here we rst pass the message to IsDialogMessage(), if the message is destined for our toolbar (indicated
by the window handle we pass in) the system will perform the default processing and return TRUE. Is this
case the message has already been handled so we don't want to call TranslateMessage() or DispatchMessage().
If the message is for another window we process as usual.
It's also worth noting that IsDialogMessage() can also be used with windows that aren't dialogs in order
to to give them dialog-like behaviour. Remember, a dialog is a window, and most (if not all) dialog APIs
will work on any window.
And that is pretty much all there is to modeless dialogs! One issue that may arise is if you have more
than one toolbar... what do you do? Well one possible solution is to have a list (either an array, an STL
std::list, or similar) and loop through it in your message loop passing each handle to IsDialogMessage() until
the right one is found, and if none, do the regular processing.
Example Program for Modeless dialog

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 92

Create an application named ModelessDialog by selecting the project type Win 32 Application in the
appwizard and click OK. Now an empty project without using MFC classes is created. Design the Menu
resource with the options Dialog and File. Under the option Dialog include the options Show and Hide.
These two options is to make your dialog visible and invisible in the output window. Under the option File
include Exit to close the output window. After designing the menu open the dialog resource and design it as
shown in gure 3.3.5(a). Next step is to save the script with .rc extension and then include this .rc le and
resource.h header le in your project. Change the ID for menu as IDR_MYMENU and the ID for dialog as
IDD_DIALOG.

Figure 3.3.5(a) Dialog design for ModelessDialog program


Click File->New and then select the option C++ Source File and give a name to the .cpp implemen-
tation le (here the name is ModelessDialog.cpp). Enter the code given below in the implementation le
(ModelessDialog.cpp).
#include <windows.h>
#include "resource.h"
const char g_szClassName[] = "myWindowClass";
HWND g_hToolbar = NULL;
BOOL CALLBACK ToolDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_PRESS:
MessageBox(hwnd, "Hi!", "This is a message",
MB_OK | MB_ICONEXCLAMATION);
break;
case IDC_OTHER:
MessageBox(hwnd, "Bye!", "This is also a message",
MB_OK | MB_ICONEXCLAMATION);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 93

{
switch(Message)
{
case WM_CREATE:
g_hToolbar=CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG),
hwnd, ToolDlgProc);
if(g_hToolbar != NULL)
{
ShowWindow(g_hToolbar, SW_SHOW);
}
else
{
MessageBox(hwnd, "CreateDialog returned NULL", "Warning!",
MB_OK | MB_ICONINFORMATION);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case ID_DIALOG_SHOW:
ShowWindow(g_hToolbar, SW_SHOW);
break;
case ID_DIALOG_HIDE:
ShowWindow(g_hToolbar, SW_HIDE);
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
DestroyWindow(g_hToolbar);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 94

wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
if(!IsDialogMessage(g_hToolbar, &Msg))
{TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
return Msg.wParam;
}
Compile, Build and Execute the program. The output is as shown in gures 3.3.5(b) through 3.3.5(d).

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 95

Figure 3.3.5(b) Running Instance of ModelessDialog Program

Figure 3.3.5(c) Running Instance of ModelessDialog Program

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 96

Figure 3.3.5(d) Running Instance of ModelessDialog Program

18.1 3.3.6 Bitmaps


Bitmaps can be loaded much like icons in earlier examples, there is LoadBitmap() for the most basic func-
tionality of simply loading a bitmap resource, and LoadImage() can be used to load bitmaps from a *.bmp
le just as it can for icons.
One of the quirks of GDI is that you can't draw to bitmap objects (HBITMAP type) directly. Remember
that drawing operations are abstracted by Device Contexts, so in order to use these drawing functions on
a bitmap, you need to create a Memory DC, and then select the HBITMAP into it with SelectObject().
The eect is that the "device" that the HDC refers to is the bitmap in memory, and when you operate on
the HDC, the resulting graphic operations are applied to the bitmap. As I mentioned, this is actually a
very convenient way of doing things, as you can write code that draws to an HDC and you can use it on a
Window DC or a Memory DC without any checks or changes. You do have the option of manipulating the
bitmap data in memory yourself. You can do this with Device Independent Bitmaps (DIB), and you can
even combine GDI and manual operations on the DIB.

18.2 GDI Leaks


Once you're nished with an HDC, it's very important to release it (just how you do that depends on how
you got it, which we'll talk about in a bit). GDI objects are limited in number. In versions of windows prior
to Windows 95, they were not only incredibly limited but also shared system wide, so that if one program
used up too many, none of the rest would be able to draw anything! Fortunately this isn't the case any
longer, and you could get away with using up quite a lot of resources in Windows 2000 or XP before anything
too bad happened... but it's easy to forget to free GDI objects and they can quickly run your program out of
GDI resources under Windows 9x. Theoretically you shouldn't be able to drain the system of GDI resources
in NT systems (NT/2K/XP) but it still happens in extreme cases.
If your program runs ne for a few minutes and then starts drawing strangely or not at all, it's a good
sign that you're leaking GDI resources. HDCs aren't the only GDI objects you need to be careful about
releasing, but generally it's ok to keep things like bitmaps and fonts around for the entire lifetime of your
program, since it's much more ecient than reloading them each time you need them.
Also, an HDC can only contain one of each type of object (bitmap, font, pen...) at a time, and when you

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 97

select a new one in it will return the last one. It's very important that you deal with this object properly. If
you ignore it completely, it will be lost and they will pile up in memory causing GDI leaks. When an HDC
is created, it's also created with some default objects selected into it... it's a good idea to store these when
they are returned to you, and then when you are completed drawing with the HDC select them back into
it. This will not only remove any of your own objects from the HDC (which is a good thing) but it will also
cause the default objects to be properly disposed of when you release or destroy the HDC (a VERY good
thing).

18.3 Displaying Bitmaps


The simplest drawing operations on a window occur by handling WM_PAINT. When your window is rst
displayed, restored from being minimized, or uncovered from having another window on top of it, Windows
sends the WM_PAINT message to the window to let it know that it needs to redraw it's contents. When
you draw something on the screen it is NOT permanent, it's only there until something else draws over it,
and at that point you need to draw it again when the time comes.
HBITMAP g_hbmBall = NULL;
case WM_CREATE:
g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));
if(g_hbmBall == NULL)
MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);
break;
The rst step is of course loading the bitmap, this is quite simple with a bitmap resource, and there are
no signicant dierences from loading other resource types. Then we can get down to drawing...
case WM_PAINT:
{
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = SelectObject(hdcMem, g_hbmBall);
GetObject(g_hbmBall, sizeof(bm), &bm);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
}
break;

18.3.1 Getting the Window DC


To start o we declare a couple of variables we need. Notice that the rst one is a BITMAP, not an
HBITMAP. BITMAP is a struct that holds information about an HBITMAP which is the actual GDI
object. We need a way to get the height and width of the HBITMAP so we use GetObject() which contrary
to it's name doesn't really get an object, but rather information about an existing one. "GetObjectInfo"
would have been a more appropriate label. GetObject() works for various GDI object types which it can
distinguish based on the value of the second parameter, the size of the structure.
The PAINTSTRUCT is a structure that contains information about the window being painted and what
exactly is going on with the paint message. For most simple tasks, you can simply ignore the information
it contains, but it's required for the call to BeginPaint(). BeginPaint() as it's name suggests is designed
specically for handling the WM_PAINT message. When not handling a WM_PAINT message you would

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 98

use GetDC() which we will see in the timer animation examples in a while... but in WM_PAINT, it's
important to use BeginPaint() and EndPaint().
BeginPaint() returns us an HDC that represents the HWND that we pass to it, the one that WM_PAINT
is being handled for. Any drawing operation we perform on this HDC will immediately display on the screen.

18.3.2 Setting up a Memory DC for the Bitmap


As mention above, in order to draw on or with bitmaps, we need to create a DC in memory... the easiest
way to do that here is to CreateCompatibleDC() with the one we already have. This gives us a Memory DC
that is compatible with the color depth and display properties of the HDC for the window.
Now we call SelectObject() to select the bitmap into the DC being careful to store the default bitmap so
that we can replace it later on and not leak GDI objects.

18.3.3 Drawing
Once we've gotten the dimensions of the bitmap lled into the BITMAP struct, we can call BitBlt() to copy
the image from our Memory DC to the Window DC, thus displaying on the screen. As always, you can look
up each parameter in MSDN, but in short they are: The destination, the position and size, the source and
source position, and nally the Raster Operation (ROP code), which species how to do the copy. In this
case, we want a simple exact copy of the source made, no fancy stu.
BitBlt() is probably the all time happiest function in all of the Win32 API and is the staple diet of anyone
learning to write games or other graphics applications in windows.

18.3.4 Cleanup
At this point the bitmap should be on the screen, and we need to clean up after ourselves. The rst thing
to do is restore the Memory DC to the state it was when we got it, which means replacing our bitmap with
the default one that we saved. Next we can delete it altogether with DeleteDC().
Finally we release the Window DC we got from BeginPaint() using EndPaint(). Destroying an HDC is a
little confusing sometimes because there are at least 3 ways to do it depending on how you got it in the rst
place. Here's a list of the common methods of gaining an HDC, and how to release it when you're done.

• GetDC() - ReleaseDC()
• BeginPaint() - EndPaint()
• CreateCompatibleDC() - DeleteDC()

And nally, at the termination of our program, we want to free any resources that we allocated. Technically
speaking this isn't absolutely required, since modern Windows platforms are pretty good at freeing everything
when your program exists, but it's always a good idea to keep track of your own objects because if get lazy
and don't delete them they have a habit of getting loose. And no doubt, there are still bugs in windows
especially older versions that won't clean up all of your GDI objects if you don't do a thorough job.
case WM_DESTROY:
DeleteObject(g_hbmBall);
PostQuitMessage(0);
break;
Example Bitmap Program
Create an application named BitmapDemo by selecting the project type Win 32 Application in the
appwizard and click OK. Now an empty project without using MFC classes is created.
Click Insert->Resource from the menu and then select the Bitmap option. Design the Bitmap as shown
in gure 3.3.6(a).

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 99

Figure 3.3.6(a) Bitmap design for the program


Save the Bitmap design in your project and then include the .rc and resource.h header le to your project
workspace. Change the ID for Bitmap as IDB_BALL Click File->New and then select the option C++
Source File and give a name to the .cpp implementation le (here the name is Bitmap.cpp). Enter the code
given below in the implementation le (Bitmap.cpp).
#include <windows.h>
#include "resource.h"
const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HBITMAP g_hbmBall;
HINSTANCE hInstance;
switch(msg)
{
case WM_CREATE:
hInstance=((LPCREATESTRUCT) lParam)->hInstance;
g_hbmBall = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BALL));
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_PAINT:
{
// Just a note, never use a MessageBox from inside WM_PAINT
// The box will cause more WM_PAINT messages and you'll probably end up
// stuck in a loop
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, g_hbmBall);
GetObject(g_hbmBall, sizeof(bm), &bm);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
DeleteDC(hdcMem);

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 100

EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
DeleteObject(g_hbmBall);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"A Bitmap Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

http://cnx.org/content/m14425/1.1/
Connexions module: m14425 101

while(GetMessage(&Msg, NULL, 0, 0) > 0)


{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Compile, Build and Execute the program. The output is as shown in gure 3.3.6(b).

Figure 3.3.6(b) Running Instance of Bitmap Program


Exercises 3

1. What are the various button styles that can be used in Windows Programming?
2. Explain the functions SetDlgItemText and GetDlgItemText.
3. Explain the List Box and Scroll Bar Class.
4. Explain the LoadIcon and LoadBitmap functions.
5. Explain SetMenu and LoadMenu functions.
6. What are the advantages of using Dialog Box?
7. Dierentiate Modal Dialog and Modeless Dialog.
8. Explain the BitBlt function.
9. Write a Windows program to add and removo items in a List box.
10. Write a Windows program to display a Bitmap in the centre of the screen.

http://cnx.org/content/m14425/1.1/

You might also like