Click here to Skip to main content
15,878,852 members
Articles / Desktop Programming / WTL
Article

WTL wrappers for WinMain's CodeMax syntax highlighting edit control

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
28 May 2001CPOL6 min read 137.8K   1.5K   36   22
An article on the CodeMax editing control.

Sample Image

Introduction

When I first started writing this article, I had planned only to illustrate how to use the CodeMax syntax editing control wrappers I had created. I quickly found though, that I would also need to explain what it was I was doing in the demo application itself. So, instead of simply releasing the set of wrappers and a demo program, I decided to write a small article on the CodeMax wrappers, meanwhile expanding on some of the things I discovered while writing an MDI application using the Windows Template Library (WTL).

Let me start by telling you a little about how the sample code is laid out. If you've ever used the WTL wizard, you are familiar with the fact that it shoves all of the application's code into a set of header files. While I like to put my components into a single header file, to simplify integration, I hate to work with application code that is set-up in this manner. So, the first thing I did was split the code up into its respective source and header files. This gives a much cleaner implementation, and in my opinion, it is easier to read and edit.

Unfortunately, by doing this, I destroyed any chance I might have had of using the 'Add Windows Message Handler' wizard that Visual C++ was nice enough to provide. But, I also opted to use the 'extended' message map (BEGIN_MSG_MAP_EX, etc.) that WTL implements, which is also incompatible with the above-mentioned wizard. So, in the end, it would have been useless anyway.

The CodeMax Wrappers

The wrappers that I included encapsulate almost everything CodeMax has to offer. I say, almost, because I have yet to implement a central way of updating the CodeMax control's settings (when you run the sample, you will see what I mean).

The classes are all defined in the cmaxwtl.h file, and all of the classes are declared within the cmax namespace.

  • CodeMaxLibrary - Wraps all the basic CodeMax library calls, including registration and unregistration.
  • CodeMaxControl - Wraps the CodeMax control itself.
  • CodeMaxControlNotifications - Base class that allows you to handle notification messages from the CodeMax control (reflected or not).
  • CodeMaxControlCommands - Base class that handles the standard CodeMax commands (cut, copy, paste, etc.).
  • UndoBlock - Simple undo helper, allows you to group a series of undoable commands as one.

How to use the wrappers

First, you will need to declare an instance of the CodeMaxLibrary object and initialize it.

// ...

CodeMaxLibrary cmaxlib;

if ( !cmaxlib.Initialize () ) {

    ATLTRACE ( _T ( "CodeMax initialization failed!\n" ) );
    
    return 0; // bail...

}     

// ...

While it does not really matter where you do this, it's best to do it early off in the game so as to avoid any hassles later on. I recommend you do it in your WinMain function or the Run function that the wizard declares for you.

Next, you will need to modify your 'view' or client window, and derive it from the CodeMaxControl class.

Note that you need to use DECLARE_WND_SUPERCLASS() in the class declaration. This allows you to superclass the window, and thereby create a window based on the CodeMax control with a new window procedure that you will later define.

class CCodeMaxWTLSampleView : 
      public CWindowImpl < CCodeMaxWTLSampleView, CodeMaxControl >
{  
   // ...
   
public:

   // Superclass the CodeMax control   

   DECLARE_WND_SUPERCLASS ( NULL, CodeMaxControl::GetWndClassName () )
   
   // ...

}

I have also included the CodeMaxControlNotifications class to allow you to handle the CodeMax control's notification messages. This class can be used as a base for either the view or the main frame. In the sample, I use it in the view, but there may be some good reasons to use it in the application's main frame. If you do decide to use it in the main frame of the application, be sure to forward all the child window's messages to the main frame. In the case of an MDI application, placing a call to FORWARD_NOTIFICATIONS() in your MDI child's message map will do this.

Our new view, with notification handling, would look something like this:

class CCodeMaxWTLSampleView : public CWindowImpl < CCodeMaxWTLSampleView, CodeMaxControl >,
                              public CodeMaxControlNotifications < CCodeMaxWTLSampleView >
{
   // ...
   
public:

   // Superclass the CodeMax control   

   DECLARE_WND_SUPERCLASS ( NULL, CodeMaxControl::GetWndClassName () )
   
  // ...

};

Of course, you still have to reflect the notification messages back to the view from its parent window and chain the notification class' message map in your view's message map.

Reflection

In MFC, we did not have to really worry about reflecting messages. All one needed to do was subclass a window or control, and all of its notification messages would be reflected back for you. In WTL, this is not the case, you actually have to reflect the messages back from the parent window to its child. Luckily, this is not all that difficult, since ATL provides us with a quick and simple method of doing this. All you have to do is remember to add REFLECT_NOTIFICATIONS() to your parent window's message map. The beauty of this macro is that it allows you to handle everything about a window within the class that defines it.

The following piece of code demonstrates how to reflect messages back to the child that sent them:

class CChildFrame : public CMDIChildWindowImpl < CChildFrame >
{ 
  
   // ...
   
   BEGIN_MSG_MAP_EX ( CChildFrame )
   
      // ...
      //
      // Notification handlers
      //      

      // Reflect all the WM_NOTIFY messages to the client window

      REFLECT_NOTIFICATIONS ()
      
   END_MSG_MAP ()
   
   // ...
  
};

Message Changing

One of the most powerful concepts offered for window centric programming, by ATL and WTL alike, is message changing. This allows you to divide the already flexible message-handling scheme into smaller, more manageable parts. What this enabled me to do was provide CodeMaxControlCommands, a class that handles all of Windows' standard command messages. Basic handling is provided for commands such as Cut & Paste and Undo/Redo.

To reap the benefit of this class, you can either derive your view from it, or as with the notification handler class, the main frame window. As you may have gathered, this is not all that you have to do. You must also make sure that the command messages are passed down from the main frame to the view. Remember that if you are using an MDI interface, the messages must first pass through the child frame before they arrive at the view.

The following macros will make this possible (both of which are defined in atlframe.h):

  • CHAIN_MDI_CHILD_COMMANDS()
  • CHAIN_CLIENT_COMMANDS()

The first one goes in the main frame's message map, where it simply passes control to the active MDI child window. The second picks up the control from the main frame and passes it to the child's client control (namely the view).

The main frame window:

class CMainFrame : public CMDIFrameWindowImpl < CMainFrame >, 
                   public CUpdateUI < CMainFrame >,
                   public CMessageFilter, 
                   public CIdleHandler
{ 
   
   // ...
   
   BEGIN_MSG_MAP_EX ( CMainFrame )
   
      // ...
      //
      // Chained Message maps
      //        

      // Pass all unhandled WM_COMMAND messages to the active child window
      CHAIN_MDI_CHILD_COMMANDS ()
         // other chains...
     
   END_MSG_MAP ()
   
   // ...
  
};

The child frame window:

class CChildFrame : public CMDIChildWindowImpl < CChildFrame >
{ 
   // ...
  
   BEGIN_MSG_MAP_EX ( CChildFrame )
   
      // ...
      //
      // Chained Message maps
      //
      
      // Pass all unhandled WM_COMMAND messages to the client window or 'view'

      CHAIN_CLIENT_COMMANDS ()
         // other chains...
      
      // ...
   
   END_MSG_MAP ()
   
   // ...
   
};

We are now free to handle any or all of the command messages in the view.

The final rendition of our view would look something like this:

class CCodeMaxWTLSampleView : 
      public CWindowImpl < CCodeMaxWTLSampleView, CodeMaxControl >,
      public CodeMaxControlNotifications < CCodeMaxWTLSampleView >,
      public CodeMaxControlCommands < CCodeMaxWTLSampleView > 
{  
   // ...

public:

   // Superclass the CodeMax control   
   DECLARE_WND_SUPERCLASS ( NULL, CodeMaxControl::GetWndClassName () )
   
   // View's message map
   BEGIN_MSG_MAP_EX ( CCodeMaxWTLSampleView )    
   
      // ...
      //
      // Chained Message maps
      //

      // Make sure that the notification
      // and default message handlers get a crack at the messages

      CHAIN_MSG_MAP_ALT ( CodeMaxControlNotifications < CCodeMaxWTLSampleView >, 
           CMAX_REFLECTED_NOTIFY_CODE_HANDLERS )
      CHAIN_MSG_MAP_ALT ( CodeMaxControlCommands < CCodeMaxWTLSampleView >, 
           CMAX_BASIC_COMMAND_ID_HANDLERS )
      
   END_MSG_MAP ()    
        
   // ...
}

The End

Well, that about wraps it up (pardon the pun); if I've forgotten something, please let me know. For those of you doing the MFC thing, I have full MFC versions of the wrappers as well... if you'd like them, just drop me a line; if the demand is high enough I'll post them.

Wanted

  1. Loosely tied mechanism to update the CodeMax control from outside the wrapper classes.
  2. A way to load and modify custom languages from disk. (I have included the beginnings of my attempt to do this, but be warned, it breaks so many rules, it's unreal. I am positive there is a more elegant way of doing it.)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Farmer's Edge
Canada Canada
Ben was born in New Zealand and grew up in Mexico; however, he has lived in Canada for most of his adult life. He has traveled to a few places in Canada so far: British Columbia, Saskatchewan, Manitoba, Ontario and Nova Scotia, but has only ever lived in Alberta — all over Alberta. From Lethbridge to Calgary to Fort McMurray: he has seen most of what the province has to offer. He has also left the comfort of his—at the time—home country and gone abroad. In recent history he has been in China, New Zealand, the US, Central America and back to Canada (where he now resides).

He completed a degree at the University of Lethbridge, in Computer Science; worked for the University of Wisconsin-Madison in the Computer Sciences Department as a Systems Programmer for the Condor Research Project[^]; and is currently completing another degree at the University of Lethbridge, once again, in Computer Science.

Ben has been known to enjoy reading, watching movies, playing console games, and learning everything he can about computers. And, more importantly, with regards to his character: does not usually speaks about himself in the third person.

Comments and Discussions

 
QuestionRaul Pin
Member 44252587-Sep-09 13:50
Member 44252587-Sep-09 13:50 
Generalhyper link Pin
hero in the forest28-Oct-05 3:09
hero in the forest28-Oct-05 3:09 
how to create the hyper link text in the client
QuestionHow to get the line number clicked by mouse? Pin
freehawk27-Jan-04 23:43
freehawk27-Jan-04 23:43 
GeneralTry Scintilla!!! Pin
ideras11-Jul-03 7:54
ideras11-Jul-03 7:54 
GeneralRe: Try Scintilla!!! Pin
Ben Burnett11-Jul-03 8:36
Ben Burnett11-Jul-03 8:36 
GeneralVC7 Build Errors: MIDL2096 : duplicated attribute Pin
soulcoder3-Jul-03 5:42
soulcoder3-Jul-03 5:42 
GeneralRe: VC7 Build Errors: MIDL2096 : duplicated attribute Pin
wps884825-Nov-03 21:26
wps884825-Nov-03 21:26 
Questionhow can i highlight .... Pin
soruc11-Mar-03 22:59
soruc11-Mar-03 22:59 
GeneralUnicode Pin
dirkp22-Dec-02 12:52
dirkp22-Dec-02 12:52 
GeneralRe: Unicode Pin
Gil Rivlis22-Jan-03 8:19
Gil Rivlis22-Jan-03 8:19 
GeneralGet a copy of CodeMax Pin
Alexandru Savescu9-Jun-02 7:26
Alexandru Savescu9-Jun-02 7:26 
GeneralRe: Get a copy of CodeMax Pin
Alexandru Savescu9-Jun-02 7:46
Alexandru Savescu9-Jun-02 7:46 
GeneralCodeMax is retiring Pin
Uwe Keim1-Oct-01 19:20
sitebuilderUwe Keim1-Oct-01 19:20 
GeneralRe: CodeMax is retiring Pin
Ben Burnett2-Oct-01 14:19
Ben Burnett2-Oct-01 14:19 
GeneralRe: CodeMax is retiring Pin
22-Jan-02 6:10
suss22-Jan-02 6:10 
GeneralRe: CodeMax is retiring Pin
MJ23-Jan-02 13:15
MJ23-Jan-02 13:15 
GeneralRe: CodeMax is retiring Pin
Philippe Lhoste18-Mar-02 2:21
Philippe Lhoste18-Mar-02 2:21 
GeneralError: File not found editx.tlb Pin
3-Aug-01 1:44
suss3-Aug-01 1:44 
GeneralRe: Error: File not found editx.tlb Pin
7-Jun-02 1:58
suss7-Jun-02 1:58 
GeneralRe: Error: File not found editx.tlb Pin
lonedfx1-Mar-03 15:36
lonedfx1-Mar-03 15:36 
GeneralError 404 Pin
Paul Barrass30-May-01 6:48
Paul Barrass30-May-01 6:48 
GeneralRe: Error 404 Pin
3-Jun-01 19:24
suss3-Jun-01 19:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.