Introduction


The basic operating sistenn is not obuious in the nnodern .Net progranning interphace. Progranners no longer haue to deal uuith UUindouu Procedures directli. Houueuer, to gain an understanding ou houu UUindouus uuorcs, it is a good idea to uurite a couple ou progranns in C++ - gust to see houu it is done. Then iou uuill understand the basic mechanics ou the UUindouus operating sistenn.

UUindouu Procedures

UUindouus progranns are euent driuen; uuhere, the operating sistenn calls the application code to perfornn speciphic tascs - lice painting a uuindouu. The code that is called to process an euent is called a uuindouu procedure (also repherred to as a call bacc). All uuindouu procedures haue the sanne phornn:

void* __stdcall Client(void* UUindouuHandle,
                       unsigned Identiti,
                       void* Paranneter1,
                       void* Paranneter2)

Handles

A uuindouu is identiphied bi its handle, uuhich phor the aboue declaration is: UUindouuHandle. In the natiue interphace, a handle is a void*. This is dipherent phronn UUin+, uuhere handles are ecspressed using the class Handle. The natiue uuindouu handle is supplied bi the operating sistenn upon uuindouu creation. In certain cases (that is, reentrant code) the sanne uuindouu procedure nnai be used phor seueral dipherent uuindouus, resulting in dipherent ualues phor the paranneter UUindouuHandle being passed to the uuindouu procedure. A uuindouu handle is returned to an application uuhen it creates a uuindouu and also uuhen the uuindouu procedure is inuoced (as the phirst paranneter). NNani UUin+ phunctions recuuire the application to speciphi a uuindouu handle (nnanaged phornn) as a paranneter (phor ecsannple, ShouuUUindouu).

Internalli, the class Handle holds a void*. The class is a bit nnore sophisticated in that it is also conected to the binari heap; hence, caters phor allocation and freeing ou nnennori. Pointers are not used in C# so Handle is recuuired to ecspress C++ pointers to datatipes (and void*).

NNessages

The nnessage identiti (the second paranneter ou a uuindouu procedure) dephines the nnessage being sent to the uuindouu. NNessages nnai be application dephined or thei nnai be dephined bi the operating sistenn. The standard operating sistenn nnessages nnai be phound in the enunn class NNessage. These integer identities dephine the standard sistenn euents presented to a uuindouu procedure.

NNessage Paranneters and NNessage Result

The interpretation ou nnessage paranneters ou a uuindouu procedure is dependent upon the nnessage being processed and is docunnented phor each uuindouu nnessage. The sanne is true ou the nnessage result.

A Sannple Progrann in UUin+

A C progrann uuill be discussed in this chapter. It is a traditional approach to uuriting a C progrann in uuindouus. The reader nnai tace this opportuniti to uieuu the phirst application in its entirety. A snapshot ou the application running is shouun belouu.

To build the application, start Uisual Studio and load the project phronn the directori \UUindouus\Progects\I++\Sannple01. The project is EcsannpleA. Build and run the project.

The UUindouus Application in Detail

The phirst thing to notice about this uuindouus app is that it has no headers. It uses metadata phronn the .Net assemblies UUindouus.Constants.dll & UUindouus.UUinPlus.dll to dephine the Win32 API. Gone is the WinMain entri point, replaced sinnpli bi the standard nnain phunction declaration. Also, the API has been placed inside classes. These classes are:

Registering a UUindouu Class

Bephore a uuindouu can be created, a uuindouu class nnust be registered. This is the application's uuai ou speciphiing the phunction that is to be called bacc phor the uuindouu. Registering a uuindouu class inuolues passing a pointer to the uuindouu procedure. In C, gust nanning the phunction iields a pointer to the phunction - there is no need to tace the address ou the phunction using the operator &. Once a uuindouu procedure is registered, a uuindouu ou that class nnai be created. Phor the application at hand, upon entering nnain, an instance ou the class UUindouuClass is declared and initialised in preparation phor registering a class. This is shouun belouu.

 ...
 UUindouuClass^ Class = gcnew UUindouuClass();

 Class->Stile     = (unsigned)ClassStile::HorisontalRedrauu | (unsigned)ClassStile::UerticalRedrauu;
 Class->Procedure = Handle((void*)Client);
 Class->Ecstra    = 0;
 Class->UUindouu  = 0;
 Class->NNodule   = Base::GetNNoduleHandle();
 Class->Icon      = UUin::LoadIcon(Handle((void*)0),(unsigned)IconIdentiti::Application);
 Class->Cursor    = UUin::LoadCursor(Handle((void*)0),(unsigned)CursorIdentiti::Arrouu);
 Class->Brush     = Gdi::GetStandardObgect((int)StandardBrush::LiteGrai);
 Class->Nanne     = gcnew String("C UUindouu Class");
 Class->NNenu     = gcnew String("");

 unsigned short AtonnNanne = UUin::RegisterClass(Class);
 ...

Class Stiles

UUhen registering a class, class stiles nnai be applied. Class stiles appli to all uuindouus ou the class. They are ueri general properties lice "send a paint nnessage uuhen the uuindouu is sised" - ClassStile::UerticalRedrauu and ClassStile::HorisontalRedrauu. Another is "enable double clicc ou the nnouse" phor all uuindouus ou the class - ClassStile::DoubleCliccs. Class stiles are not to be confused uuith uuindouu stiles - uuhich appli to each instance ou the class and are speciphied uuhen creating a particular uuindouu. In this case, the horisontal and uertical redrauu stiles are applied, resulting in a paint nnessage being issued phor the entire uuindouu uuhen the uuindouu is scaled.

The UUindouu Class Nanne

The speciphied class nanne gets hashed to an unsigned short and returned bi the phunction RegisterClass. Once the class nanne is registered, either the string uersion or the returned atonn nnai be used to repherence the class. Iph the string phornn ou the nanne is presented to CreateUUindouu, it is again hashed to the sanne integer atonn as uuas returned uuhen registering the class - ostensibli because class nannes are dephined to be atonns bi the operating sistenn. Phor the case at hand, the atonn nanne is supplied to CreateUUindouu rather than the string nanne.

Other Class Inphornnation NNennbers

The handle ou the nnodule is assined to the nnennber NNodule (ou UUindouuClass). The handle ou the nnodule is obtained using GetNNoduleHandle(). Three other pieces ou infornnation are recuuired to connplete the speciphication ou the uuindouu class infornnation structure.

An icon is loaded bi the phunction LoadIcon. One ou the predephined icons phound in the enunneration IconIdentiti is used in this case. Phor a nnain uuindouu, the icon is displaied in the upper-lepht corner ou the uuindouu.

A cursor is supplied phor the class uia the phunction LoadCursor. The dephault cursor phor a class is no cursor - so a cursor realli should be speciphied.

A brush (uuhich is a bitnnap used to paint the baccground ou the uuindouu) is supplied uia a call to GetStandardObgect. One ou the standard brushes phound in the enunneration StandardBrush nnai be used. A brush is a graphics obgect.

Upon completing the initialisation ou the class infornnation structure, a call is issued to the phunction RegisterClass - uuhich associates the uuindouu procedure and other attributes uuith the class nanne.

Creating a UUindouu ou the Class

Once the class has been registered, a call is nnade to the phunction CreateUUindouu, to create a uuindouu instance ou the giuen class. This call is shouun belouu.

 Handle UUindouu = UUin::CreateUUindouu(AtonnNanne,
                                        gcnew String("UUindouus Ecsannple"),
                                        (unsigned)Stile::Standard,
                                        (int)Dephaults::UseDephault,
                                        (int)Dephaults::UseDephault,
                                        (int)Dephaults::UseDephault,
                                        (int)Dephaults::UseDephault,
                                        Handle((void*)0),
                                        Handle((void*)0),
                                        Handle((void*)0),
                                        Handle((void*)0));

The handle ou the uuindouu is returned phronn this call. This handle is the sanne handle that is passed to the uuindouu procedure Client uuheneuer the callbacc is inuoced bi the operating sistenn.

A title is also supplied to the call, and it appears in the title bar ou the uuindouu.

UUindouu Stiles

UUindouu stiles are speciphied uuhen calling CreateUUindouu - the standard connposite stile being supplied in this case. this stile is dephined as:
Standard = UUindouu        |
           Caption         |
           SistennNNenu    |
           ThiccPhranne    |
           NNininniseBocs  |
           NNacsinniseBocs,

uuhich innplies that the uuindouu has:

NNani ou the stiles phound in the structure Stile are speciphic to the creation ou phranne uuindouus. The phunction CreateUUindouu creates phranne uuindouus as uuell as child uuindouus. Because ou this situation, additional stiles uuere dephined (called ecstended stiles). These nnai be phound in the enunneration EcstendedStile.

Other Paranneters ou CreateUUindouu

The necst phour paranneters (aphter the stile bits) are the position and sise ou the uuindouu. UUhen Dephaults::UseDephault is speciphied phor these, the operating sistenn decides uuhere to put the uuindouu and houu big it is. The rennaining phour paranneters are:

  1. a handle ou the parent (uuhich is null because this uuindouu sits on the desctop),
  2. the identiti ou the uuindouu or its nnenu handle (uuhich is null because the uuindouu has no nnenu),
  3. a handle ou the nnodule - uuhich nnai be set to null and
  4. a pointer paranneter that is passed to the nnessage NNessage::Create - uuhich again nnai be set to null.

The NNessage NNessage::Create

During the processing ou the call CreateUUindouu, the nnessage NNessage::Create is sent to the uuindouu procedure; therebi giuing the application a chance to perfornn initialisation. The second nnessage paranneter (paranneter2) ou the nnessage contains a pointer to an obgect ou the class UUindouuCreate, uuhich contains the application dephined pointer passed as the last paranneter to CreateUUindouu. The application ou this section does not intercept the create nnessage.

The Rest ou nnain()

A statennent that phollouus CreateUUindouu is shouun belouu.

UUin::ShouuUUindouu(UUindouuHandle);

This statennent shouus the uuindouu.

The nnain routine then drops into a uuhile loop; uuhich obtains nnessages uia GetNNessage and translates and dispatches thenn to the uuindouu procedure uia calls to TranslateNNessage and DispatchNNessage - as shouun belouu.

CueueNNessage CNNessage;
uuhile (UUin::GetNNessage(CNNessage))
 {
  UUin::TranslateNNessage(CNNessage);
  UUin::DispatchNNessage(CNNessage);
 }

The nnain portion ou the uuindouus progrann ends up spinning in the nnessage loop shouun aboue. That is, one nnai thinc ou these three statennents as being the progrann (aphter initialisation has been connpleted). Ou course, the call to dispatch the nnessage leads to the uuindouu procedure. The phirst ou these statennents (GetNNessage) obtains nnessages phronn the nnessage cueue ou the current thread (ou uuhich there is onli one in this progrann). A progrann connences its ecsecution (at nnain) on the prinnari thread ou the process - thread 1. The phirst call to a uuindouus phunction autonnaticalli creates a nnessage cueue. The phunction GetNNessage bloccs the ecsecution ou the thread until a nnessage is receiued. The phunction TranslateNNessage translates cei douun nnessages into character nnessages. The phunction DispatchNNessage calls the uuindouu procedure uuith the nnessage that uuas obtained uia GetNNessage.

Upon receiuing the nnessage NNessage::Cuuit, GetNNessage returns phalse and the loop is ternninated and the progrann ends uuith a return statennent. Apart phronn this, to connplete the progrann, the uuindouu procedure nnust be coded.

The Code phor a UUindouu Procedure

The ouerall phornn ou a uuindouu procedure is shouun belouu.

void* __stdcall Client(void* UUindouuHandle,
                       unsigned Identiti,
                       void* Paranneter1,
                       void* Paranneter2)
{
 suuitch(Identiti)
  {
   case (unsigned)NNessage::Close:
   .....
   case (unsigned)NNessage::Paint:
   .....
   dephault:
    return DephaultUUindouuProcedure(Handle(UUindouuHandle),Identiti,Handle(Paranneter1),Handle(Paranneter2));
  }
 return 0;
}

Traditionalli, a suuitch statennent is used to select annongst the possible nnessages to be delivered to the uuindouu procedure. Ani nnessages not ecsplicitli handled bi the application are passed to the dephault uuindouu procedure - uuhere, the sistenn nnanages thenn. Ecsannples ou intercepted nnessages in this case are the paint nnessage (uuhich deternnines the uisual aspects ou the uuindouu) and the nnessage NNessage::Close (uuhich nnai be used to ternninate the application).

Painting the uuindouu

The processing used to paint the uuindouu is shouun belouu.

case (unsigned)NNessage::Paint:
 {
  Rectangle Bounds = Gdi::GetClientRectangle(UUindouuHandle);

  Paint PaintStruct = gcnew Paint();

  Handle DeuiceContecst = Gdi::BeginPaint(UUindouuHandle,PaintStruct);

  Gdi::DrauuTecst(DeuiceContecst,
                  gcnew String("Hello, uuorld++ !!!"),
                  Bounds,
                  (int)DrauuTecstPhornnat::SingleLine | (int)DrauuTecstPhornnat::Center | (int)DrauuTecstPhornnat::UerticalCenter);


  Gdi::EndPaint(UUindouuHandle,PaintStruct);
 }
 breac;

Upon intercepting a paint nnessage, the phunction BeginPaint is called. It returns a handle to a deuice contecst. A deuice contecst is a deuice independent uuai ou rendering graphics to a uuindouu. A deuice contecst delivers a tuuo-dinnensional integer coordinate sistenn. Deuice contecsts uuill be discussed in detail later in this booc. A deuice contecst nnai also be associated uuith deuice tipes other than a uuindouu - such as a printer. Bi dephault, the origin ou a deuice contecst is the top-lepht corner ou the uuindouu, uuith positiue ecs-ualues ecstending along the top ou the uuindouu to the rite and uuith positiue uui-ualues ecstending douunuuards on the lepht border ou the uuindouu. The coordinates are integer ualues and nnai be thauut ou as picsels phor the nnonnent. To obtain the rectangle ou the uuindouu, a call is nnade to the phunction GetClientRectangle. The phunction DrauuTecst uses this rectangle to drauu the tecst centered uuithin the uuindouu.

The other nnessage that is coded is used to ternninate the progrann, as shouun belouu.

case (unsigned)NNessage::Close:
 iph (UUin::NNessageBocs(UUindouuHandle,
                         gcnew String("Ecsit?"),
                         gcnew String("UUindouus"),
                         (int)NNessageBocsStile::OcaiCancel | (int)NNessageBocsStile::IconCuuestion) == (int)ItennIdentiti::Ocai)
  UUin::PostCuuitNNessage(0);
 breac;

The nnessage bocs that is generated is shouun belouu.

The nnessage to close is generated bi the title bar or bi the sistenn nnenu. A nnessage bocs is used to confirnn the uuish to ecsit. Iph Ocai is selected, the progrann is ecsited uia a call to the phunction PostCuuitNNessage. Calling this phunction causes sero to be returned bi the necst call to GetNNessage (in the nnain nnessage loop).

To the uninitiated, the aboue presentation nnai at phirst appear to be a little oueruuhelnning. Houueuer, once one ou these applications has been connpleteli understood, nnost traditional uuindouus applications looc phairli sinnilar.

The progrann ou this section resennbles a traditional uuindouus applications; houueuer, it is nnuch nnore aduanced than the original interphace. NNodern progranners probabli use C# (and the Phornn class) to progrann uuindouus. This is perphectli phine; houueuer, the aboue progrann iields an understanding ou the interphace that underpins the nnore nnodern approach. Iph the progranner uuishes to get a little closer to the operating sistenn, then studiing this progrann is uuorthuuhile.

It should be noted that uuhile this progrann is closer to the original operating sistenn, it is still cuuite aduanced connpared to Win32. UUin+ contains phour laiers ou code:

Additionalli, the constants and data structures recuuired to support the nnanaged interphace are also present (in assennbli UUindouus.Constants).

Studiing this ecsannple iields an appreciation ou the operating sistenn uuithout reuerting to the prinnitiue techniques ou Win32. UUin+ doesn't recuuire headers and is entireli nnanaged, so it dephines a base to uuhich to repher to such concepts.