RichEdit - Mejorando la velocidad de coloreado

RichEdit - Mejorando la velocidad de coloreado

Postby Antonio Linares » Tue Feb 28, 2012 12:14 pm

Hace unos dias estaba revisando el editor de código fuente ED de Enrico Maria Giordano http://www.emagsoftware.it/Ed106.zip. Como él me explicó:

Está escrito en C, usa el control RICHEDIT y ofrece la funcionalidad minima que necesito. Puedo proporcionar el código fuente si te puede resultar util.


Estaba interesado en revisar cuanta funcionalidad puede ofrecer RichEdit como un editor de código fuente proporcionado por el propio Windows. Recordaba que el coloreado de syntaxis en el RichEdit era lento para ficheros grandes y que ese era su principal problema. Asi que decidí investigarlo un poco más. La primera información interesante que encontré fué esta:

http://bcbjournal.org/articles/vol3/9910/Faster_rich_edit_syntax_highlighting.htm

Su autor usa C++ Builder y ha encontrado algunas maneras de optimizarlo. Asi que decidí crear un ejemplo auto contenido en lenguaje C para probar como de rápido sus optimizaciones son. Puedes construirlo facilmente usando Borland C:

go.bat
Code: Select all  Expand view
set path=c:\bcc582\bin
bcc32 -W test.c
if errorlevel 0 test


test.c // Editor basado en RichEdit con coloreado automático de sintaxis
Code: Select all  Expand view
#include <windows.h>
#include <richedit.h>
#include <stdio.h>

typedef struct
{
   char * txt;
   long len;
   FILE * out;
} COOKIE;

#define CLR_YELLOW  RGB( 255, 255,   0 )
#define CLR_HCYAN   RGB(   0, 255, 255 )
#define CLR_HGREEN  RGB(   0, 255,   0 )
#define CLR_WHITE   RGB( 255, 255, 255 )

void ParseAllText( HWND hRichEdit )
{
   LONG pos = 0, start = 1;
   CHARFORMAT cf;
   TEXTRANGE tr;
   char buffer[ 256 ];
   int eventMask = SendMessage( hRichEdit, EM_SETEVENTMASK, 0, 0 );

   SendMessage( hRichEdit, WM_SETREDRAW, FALSE, 0 );

   memset( &cf, 0, sizeof( cf ) );
   cf.cbSize = sizeof( cf );
   cf.dwMask = CFM_COLOR;
                         
   while( pos != start )
   {
      start = pos;
      pos = SendMessage( hRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, pos );

      SendMessage( hRichEdit, EM_SETSEL, start, pos );

      tr.chrg.cpMin = start;
      tr.chrg.cpMax = pos;
      tr.lpstrText  = buffer; // malloc( pos - start + 1 + 1 );
      SendMessage( hRichEdit, EM_GETTEXTRANGE, 0, ( LPARAM ) &tr );      

      if( strstr( "# define ifdef ifndef endif pragma include ", tr.lpstrText ) )
      {
         cf.crTextColor = CLR_YELLOW;      
         SendMessage( hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );
      }  
      else if( strstr( "local static extern public private nil for next if else endif do case endcase ", tr.lpstrText ) )
      {
         cf.crTextColor = CLR_HCYAN;               
         SendMessage( hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );
      }  
      else if( strstr( "function CLASS  DATA  INIT METHOD INLINE VIRTUAL SETGET ENDCLASS procedure return ",  tr.lpstrText ) )
      {
         cf.crTextColor = CLR_HGREEN;              
         SendMessage( hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );
      }  
      else if( strstr( "= + - ++ -- += -= *= /= / * < > <= >= % $ | ! ^ @ {} {}, { } {| [ ] ]: ( ) (- ), ): ); ),; () (): :: := != == += -= . , ; ,; .,; ",  tr.lpstrText ) )
      {
         cf.crTextColor = CLR_WHITE;               
         SendMessage( hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM ) &cf );
      }  
         
      // free( tr.lpstrText );
   }

   SendMessage( hRichEdit, WM_SETREDRAW, TRUE, 0 );
   SendMessage( hRichEdit, EM_SETEVENTMASK, 0, eventMask );
   InvalidateRect( hRichEdit, 0, TRUE );
}  

#pragma argsused

DWORD CALLBACK StreamIn( DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR *pcb )
{
   COOKIE * Cookie = ( COOKIE * ) dwCookie;

   if( cb > Cookie->len )
      cb = Cookie->len;

   if( cb > 0 )
   {
      memcpy( ( char * ) pbBuff, Cookie -> txt, cb );

      Cookie->txt += cb;
      Cookie->len -= cb;
   }

   * pcb = cb;

   return 0;
}

BOOL LoadText( HWND hRichEdit, const char * FileName )
{
   FILE * in = fopen( FileName, "rb" );
   int len;

   if( ! in )
      return FALSE;

   fseek( in, 0, SEEK_END );
   len = ftell( in );
   fseek( in, 0, SEEK_SET );

   if( len > 0 )
   {
      COOKIE Cookie;
      EDITSTREAM es;
      char * txt = malloc( len + 1 );

      fread( txt, 1, len, in );

      Cookie.txt = txt;
      Cookie.len = len;

      es.dwCookie    = ( DWORD ) &Cookie;
      es.pfnCallback = StreamIn;

      SendMessage( hRichEdit, EM_STREAMIN, SF_TEXT, ( LPARAM ) &es );

      free( txt );
   }

   fclose( in );
   
   return TRUE;
}

LRESULT WINAPI ParentWindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
     static HWND hRichEdit;
   static HFONT hFont;

     switch( msg )
   {
        case WM_CREATE:
               {
                  RECT r;
                  GetClientRect( hWnd, &r );
                  hRichEdit = CreateWindow( "RICHEDIT", "",
                                              WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_SUNKEN,
                                              0, 30, r.right - r.left, r.bottom - r.top - 50,
                                              hWnd, NULL, NULL, NULL );
              hFont  = CreateFont( 18, 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Courier New" );
              SendMessage( hRichEdit, WM_SETFONT, ( WPARAM ) hFont, 0 );
                  LoadText( hRichEdit, "window.prg" );
                  SendMessage( hRichEdit, EM_EXLIMITTEXT, 0, 0xFFFFFFF );
              ParseAllText( hRichEdit );
              SetFocus( hRichEdit );
               }  
             break;
       
        case WM_CLOSE:
               DeleteObject( hFont );
               DestroyWindow( hWnd );
               break;
             
        case WM_LBUTTONDOWN:
               break;
             
          case WM_SIZE:
               MoveWindow( hRichEdit, 0, 30, LOWORD( lParam ), HIWORD( lParam ) - 50, FALSE );
               break;  
               
        case WM_DESTROY:
               PostQuitMessage( 0 );
               break;
     }
   
   return DefWindowProc( hWnd, msg, wParam, lParam );
}

int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show )
{
   WNDCLASS cls;
     HWND hWnd;
     MSG msg;
   HINSTANCE hDll = LoadLibrary( "riched32" );

   cls.style         = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
   cls.lpfnWndProc   = ParentWindowProc;
   cls.cbClsExtra    = 0;
   cls.cbWndExtra    = 0;
     cls.hInstance     = hInstance;
   cls.hIcon         = LoadIcon( 0, IDI_APPLICATION );
   cls.hCursor       = LoadCursor( 0, IDC_ARROW );
   cls.hbrBackground = GetStockObject( WHITE_BRUSH );
   cls.lpszMenuName  = 0;
   cls.lpszClassName = "parentclass";

   if( ! RegisterClass( &cls ) )
        return FALSE;

   hWnd = CreateWindow( "parentClass", "RichEdit syntax highlight", WS_OVERLAPPEDWINDOW ,
                        100, 100, 1100, 600, 0, NULL, hInstance, 0 );

   ShowWindow( hWnd, SW_MAXIMIZE );
   UpdateWindow( hWnd );

     while( GetMessage( &msg, 0, 0, 0 ) )
     {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
     }

   FreeLibrary( hDll );

     return 0;
}


Nada de Harbour, ni FWH, puro lenguaje C para probar su velocidad, pero desafortunadamente aún lento para grandes ficheros PRG. Así que decidí seguir googleando y encontré esto:

http://win32assembly.online.fr/tut35.html

Puede asustar en un principio pues está desarrollado en ensamblador (ouch!) :-) pero su autor tiene una interesante idea: hacer "subclass" del control RichEdit y hacer el coloreado él mismo. Bien, decidí pasarlo desde ensamblador a lenguaje C para probarlo. Algunas partes las he implementado yo una vez entendí su intención. Aqui está:

fresh.c // Se me ocurrió este nombre como acrónimo de "Free RichEdit Editor Syntax Highlighted" :-)
Code: Select all  Expand view
#pragma resource "fresh.res"

#include <windows.h>
#include <richedit.h>
#include <stdio.h>

typedef struct
{
   DWORD    WordLen;    // the length of the word: used as a quick comparison
     char * pszWord;    // pointer to the word
     COLORREF * pColor; // point to the dword that contains the color used to hilite the word
     void * NextLink;   // point to the next WORDINFO structure
} WORDINFO;

#define IDR_MAINMENU               101
#define IDM_OPEN                 40001
#define IDM_SAVE                 40002
#define IDM_CLOSE                40003
#define IDM_SAVEAS               40004
#define IDM_EXIT                 40005
#define IDM_COPY                 40006
#define IDM_CUT                  40007
#define IDM_PASTE                40008
#define IDM_DELETE               40009
#define IDM_SELECTALL            40010
#define IDM_OPTION                   40011
#define IDM_UNDO                       40012
#define IDM_REDO                       40013
#define IDD_OPTIONDLG              101
#define IDC_BACKCOLORBOX          1000
#define IDC_TEXTCOLORBOX          1001
#define IDR_MAINACCEL              105
#define IDD_FINDDLG                102
#define IDD_GOTODLG                103
#define IDD_REPLACEDLG             104
#define IDC_FINDEDIT              1000
#define IDC_MATCHCASE             1001
#define IDC_REPLACEEDIT           1001
#define IDC_WHOLEWORD             1002
#define IDC_DOWN                  1003
#define IDC_UP                    1004
#define IDC_LINENO                1005
#define IDM_FIND                 40014
#define IDM_FINDNEXT             40015
#define IDM_REPLACE              40016
#define IDM_GOTOLINE             40017
#define IDM_FINDPREV             40018

#define RichEditID                     300

#define CLR_HRED      RGB( 255,   0,   0 )
#define CLR_HGREEN    RGB(   0, 255,   0 )
#define CLR_HBLUE     RGB(   0,   0, 255 )
#define CLR_BLACK     RGB(   0,   0,   0 )
#define CLR_WHITE     RGB( 255, 255, 255 )

char FindBuffer[ 256 ];
char ReplaceBuffer[ 256 ];
HWND hWndRichEdit;
WNDPROC OldWndProc;
int RichEditVersion;

COLORREF BackGroundColor = CLR_WHITE;
COLORREF TextColor = CLR_BLACK;
COLORREF CommentColor = CLR_HBLUE;
COLORREF ColorArray[ 10 ] = { CLR_HRED, CLR_HGREEN, CLR_HBLUE, CLR_WHITE, CLR_BLACK,
                              CLR_BLACK, CLR_BLACK, CLR_BLACK, CLR_BLACK, CLR_BLACK };  
BOOL FileOpened = FALSE;
char * szFileFilter = "PRG source code (*.prg)\0*.prg\0All Files (*.*)\0*.*\0";
char FileName[ 256 ];
char AlternateFileName[ 256 ];
HANDLE hSearch = NULL;
char * OpenFileFail = "Cannot open the file";
char * AppName = "Fresh 1.0";
char * WordFileName = "wordfile.txt";
FINDTEXTEX findtext;
char * WannaSave = "The data in the control is modified. Want to save it ?";
HFONT hFont;
WORDINFO SyntaxArray[ 256 ];

void SetColor( void )
{
     CHARFORMAT cfm;     
   
     SendMessage( hWndRichEdit, EM_SETBKGNDCOLOR, 0, BackGroundColor );
     memset( &cfm, 0, sizeof( cfm ) );
     cfm.cbSize = sizeof( cfm );
     cfm.dwMask = CFM_COLOR;
     cfm.crTextColor = TextColor;
     SendMessage( hWndRichEdit, EM_SETCHARFORMAT, SCF_ALL, ( LPARAM ) &cfm );
}

void CenterWindow( HWND hWnd )
{
   RECT rWnd, rDsk;
   LONG Left, Top, Width, Height;

   GetWindowRect( hWnd, &rWnd );
   GetWindowRect( GetDesktopWindow(), &rDsk );

   Width  = rWnd.right - rWnd.left;
   Height = rWnd.bottom - rWnd.top;
   Left   = ( rDsk.right / 2 ) - ( Width / 2 );
   Top    = ( rDsk.bottom / 2 ) - ( Height / 2 );

   MoveWindow( hWnd, Left, Top, Width, Height, FALSE );
}

void ParseBuffer( char * pszTokens, DWORD dwGroup )
{
   char buffer[ 128 ];
   char * pStart = pszTokens;
   // BOOL InProgress = FALSE;
   BOOL bFound = FALSE;
   WORDINFO * pWordInfo;
   
   if( ! strlen( pszTokens ) )
      return;
       
   CharLower( pszTokens );
   
   while( * pszTokens )
   {
      if( ( ( * pszTokens ) == ' ' ) || ( ( * pszTokens ) == 9 ) ) // tab
         bFound = TRUE
         
      if( * pszTokens && bFound )
      { 
         pWordInfo = SyntaxArray + pStart[ 0 ];

         if( SyntaxArray[ pStart[ 0 ] ].WordLen )
         {
            while( pWordInfo->NextLink )
               pWordInfo = pWordInfo->NextLink;    
               
            pWordInfo->NextLink = ( WORDINFO * ) malloc( sizeof( WORDINFO ) );  
            memset( ( void * ) pWordInfo->NextLink, 0, sizeof( WORDINFO ) );
         }  

         pWordInfo->WordLen = pszTokens - pStart;
         pWordInfo->pszWord = ( char * ) malloc( pWordInfo->WordLen + 1 );
         strncpy( pWordInfo->pszWord, pStart, pWordInfo->WordLen );
         pWordInfo->pszWord[ pWordInfo->WordLen ] = 0;
         pWordInfo->pColor = ColorArray + dwGroup - 1;
         pWordInfo->NextLink = NULL;
         bFound = FALSE;
         // MessageBox( 0, pWordInfo->pszWord, "token", 0 );
         
         while( ( ( ( * pszTokens ) == ' ' ) || ( ( * pszTokens ) == 9 ) ) && ( * pszTokens ) )
            pszTokens++;
           
         pStart = pszTokens;
      }  
     
      if( * pszTokens )
         pszTokens++;
   }      
}   

void FillHiliteInfo( void )
{
   char filename[ 1024 ];
   char buffer[ 1024 ];
   char * pTemp;
   
   RtlZeroMemory( SyntaxArray, sizeof( SyntaxArray ) )

   GetModuleFileName( GetModuleHandle( NULL ), filename, sizeof( filename ) );
   pTemp = filename + lstrlen( filename );
   
   while( ( pTemp > filename ) && ( ( * pTemp ) != '\\' ) )
      pTemp--;
     
   * ++pTemp = 0;  
   lstrcat( pTemp, WordFileName );
   
   if( GetFileAttributes( filename ) != INVALID_FILE_ATTRIBUTES )
   {
      if( GetPrivateProfileString( "ASSEMBLY", "C1", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 1 );

      if( GetPrivateProfileString( "ASSEMBLY", "C2", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 2 );
         
      if( GetPrivateProfileString( "ASSEMBLY", "C3", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 3 );

      if( GetPrivateProfileString( "ASSEMBLY", "C4", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 4 );
         
      if( GetPrivateProfileString( "ASSEMBLY", "C5", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 5 );

      if( GetPrivateProfileString( "ASSEMBLY", "C6", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 6 );

      if( GetPrivateProfileString( "ASSEMBLY", "C7", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 7 );
         
      if( GetPrivateProfileString( "ASSEMBLY", "C8", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 8 );

      if( GetPrivateProfileString( "ASSEMBLY", "C9", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 9 );
         
      if( GetPrivateProfileString( "ASSEMBLY", "C10", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 10 );
   }  
   else
      MessageBox( 0, "wordfile.txt does not exist", "Attention", MB_ICONINFORMATION );                       
}  
   
BOOL CheckModifyState( HWND hWnd )
{
     int nResult;
     
   if( SendMessage( hWndRichEdit, EM_GETMODIFY, 0, 0 ) )
        if( ( nResult = MessageBox( hWnd, WannaSave, AppName, MB_YESNOCANCEL ) ) == IDYES )
               SendMessage( hWnd, WM_COMMAND, IDM_SAVE, 0 );
            else if( nResult == IDCANCEL )
               return FALSE;
                  
   return TRUE;
}

void PrepareEditMenu( HMENU hSubMenu )
{
   CHARRANGE chrg;

     if( ! SendMessage( hWndRichEdit, EM_CANPASTE, CF_TEXT, 0 ) )
        EnableMenuItem( hSubMenu, IDM_PASTE, MF_GRAYED );
     else  
          EnableMenuItem( hSubMenu, IDM_PASTE, MF_ENABLED );

     if( ! SendMessage( hWndRichEdit, EM_CANUNDO, 0, 0 ) )
        EnableMenuItem( hSubMenu, IDM_UNDO, MF_GRAYED );
     else  
          EnableMenuItem( hSubMenu, IDM_UNDO, MF_ENABLED );

     if( ! SendMessage( hWndRichEdit, EM_CANREDO, 0, 0 ) )
          EnableMenuItem( hSubMenu, IDM_REDO, MF_GRAYED );
     else
        EnableMenuItem( hSubMenu, IDM_REDO, MF_ENABLED );

     chrg.cpMin = SendMessage( hWndRichEdit, EM_EXGETSEL, 0, ( LPARAM ) &chrg );
     
     if( chrg.cpMin == chrg.cpMax )
     { 
        EnableMenuItem( hSubMenu, IDM_COPY,   MF_GRAYED );
          EnableMenuItem( hSubMenu, IDM_CUT,    MF_GRAYED );
          EnableMenuItem( hSubMenu, IDM_DELETE, MF_GRAYED );
     }   
     else
     { 
        EnableMenuItem( hSubMenu, IDM_COPY,   MF_ENABLED );
          EnableMenuItem( hSubMenu, IDM_CUT,    MF_ENABLED );
          EnableMenuItem( hSubMenu, IDM_DELETE, MF_ENABLED );
     }   
}

#pragma argsused

static INT_PTR CALLBACK OptionProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
   switch( wMsg )
   {
      case WM_INITDIALOG:
           CenterWindow( hDlg );
           return TRUE;

      case WM_COMMAND:
           switch( wParam )
           {
              case IDOK:
                   EndDialog( hDlg, IDOK );
                   break;

              case IDCANCEL:
                   EndDialog( hDlg, IDCANCEL );
                   break;
           }
           break;
   }
   return FALSE;
}

#pragma argsused

static INT_PTR CALLBACK SearchProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
   switch( wMsg )
   {
      case WM_INITDIALOG:
           CenterWindow( hDlg );
           return TRUE;

      case WM_COMMAND:
           switch( wParam )
           {
              case IDOK:
                   EndDialog( hDlg, IDOK );
                   break;

              case IDCANCEL:
                   EndDialog( hDlg, IDCANCEL );
                   break;
           }
           break;
   }
   return FALSE;
}

#pragma argsused

static INT_PTR CALLBACK ReplaceProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
   switch( wMsg )
   {
      case WM_INITDIALOG:
           CenterWindow( hDlg );
           return TRUE;

      case WM_COMMAND:
           switch( wParam )
           {
              case IDOK:
                   EndDialog( hDlg, IDOK );
                   break;

              case IDCANCEL:
                   EndDialog( hDlg, IDCANCEL );
                   break;
           }
           break;
   }
   return FALSE;
}

#pragma argsused

static INT_PTR CALLBACK GoToProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
   switch( wMsg )
   {
      case WM_INITDIALOG:
           CenterWindow( hDlg );
           return TRUE;

      case WM_COMMAND:
           switch( wParam )
           {
              case IDOK:
                   EndDialog( hDlg, IDOK );
                   break;

              case IDCANCEL:
                   EndDialog( hDlg, IDCANCEL );
                   break;
           }
           break;
   }
   return FALSE;
}

LRESULT WINAPI NewRichEditProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
   HDC hDC;
   HFONT hOldFont;
   RECT rect;
   TEXTRANGE txtrange;
   char buffer[ 1024 * 10 ];
   HRGN hRgn, hOldRgn;
   POINT pt;
   DWORD nChar, nLine, dwPos;
   WORDINFO * pWordInfo;
   BOOL bExit;

   switch( msg )
   {
      case WM_PAINT:       
           HideCaret( hWnd );
               CallWindowProc( OldWndProc, hWnd, msg, wParam, lParam );
               hDC = GetDC( hWnd );
               SetBkMode( hDC, TRANSPARENT );
               hOldFont = SelectObject( hDC, hFont );

               SendMessage( hWnd, EM_GETRECT, 0, ( LPARAM ) &rect );
               
             nChar = SendMessage( hWnd, EM_CHARFROMPOS, 0, ( LPARAM ) &rect );
               nLine = SendMessage( hWnd, EM_LINEFROMCHAR, nChar, 0 );
               txtrange.chrg.cpMin = SendMessage( hWnd, EM_LINEINDEX, nLine, 0 );
           txtrange.chrg.cpMax = SendMessage( hWnd, EM_CHARFROMPOS, 0, ( LPARAM ) &rect.right );               
               
               hRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom );
           hOldRgn = SelectObject( hDC, hRgn );

           txtrange.lpstrText = buffer;
           if( SendMessage( hWnd, EM_GETTEXTRANGE, 0, ( LPARAM ) &txtrange ) )
           {
              char * pPos = buffer;
              char * pStart = buffer;
              char * pToken;
             
              while( * pPos )
              {
                 if( * pPos == ' ' || * pPos == 9 || * pPos == 0xD || * pPos == 0xA )
                 {
                    pToken = ( char * ) malloc( pPos - pStart + 1 );
                    strncpy( pToken, pStart, pPos - pStart );
                    pToken[ pPos - pStart ] = 0;
                    // MessageBox( 0, pToken, "token", 0 );
                   
                    if( RichEditVersion == 3 )
                                   SendMessage( hWnd, EM_POSFROMCHAR, ( WPARAM ) &rect, ( LPARAM ) ( pStart - buffer ) + nChar );
                                else  
                                {   
                                 dwPos = SendMessage( hWnd, EM_POSFROMCHAR, ( WPARAM ) pStart, 0 );
                                   rect.left = LOWORD( dwPos );
                                   rect.top  = HIWORD( dwPos );
                                }
                               
                                if( pToken[ 0 ] >= 'A' && pToken[ 0 ] <= 'Z' )
                                   pWordInfo = SyntaxArray + pToken[ 0 ] - 'A' + 'a';
                                else  
                                   pWordInfo = SyntaxArray + pToken[ 0 ];
                               
                                bExit = FALSE;
                               
                                while( pWordInfo->WordLen && ! bExit )
                                {
                                   if( strlen( pToken ) == pWordInfo->WordLen &&
                                         lstrcmpi( pWordInfo->pszWord, pToken ) == 0 )
                                   {   
                                      bExit = TRUE;
                                      SetTextColor( hDC, * pWordInfo->pColor )
                                      DrawText( hDC, pToken, -1, &rect, 0 );  
                                   }
                                   else
                                   {
                                      if( pWordInfo->NextLink )
                                         pWordInfo= pWordInfo->NextLink;
                                      else
                                         bExit = TRUE;  
                                   }               
                                }
                                   
                    free( pToken );
                   
                    while( * pPos == ' ' || * pPos == 9 || * pPos == 0xD || * pPos == 0xA && * pPos )
                       pPos++;
                       
                    if( ! * pPos )
                       pPos++;   
                       
                    pStart = pPos;    
                 }  
                 pPos++;
              }  
           }  

           SelectObject( hDC, hOldRgn );
           DeleteObject( hRgn );
           SelectObject( hDC, hOldFont );
           ReleaseDC( hWnd, hDC );
           ShowCaret( hWnd );
           return 0;
   
      case WM_CLOSE:
             SetWindowLong( hWnd, GWL_WNDPROC, ( LONG ) OldWndProc );
             break;
   }
               
   return CallWindowProc( OldWndProc, hWnd, msg, wParam, lParam );
}

DWORD CALLBACK StreamInProc( DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR * pcb )
{      
     ReadFile( ( HANDLE ) dwCookie, ( LPVOID ) pbBuff, ( DWORD ) cb, ( LPDWORD ) pcb, 0 );
   return 0;
}  

DWORD CALLBACK StreamOutProc( DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR * pcb )
{
     WriteFile( ( HANDLE ) dwCookie, ( LPVOID ) pbBuff, ( DWORD ) cb, ( LPDWORD ) pcb, 0 );
   return 0;
}  
    
LRESULT WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
     RECT rect;
   OPENFILENAME ofn;
     char buffer[ 256 ];
     EDITSTREAM editstream;
     FILE * hFile;
     HMENU hPopup;
     POINT pt;
     CHARRANGE chrg;
   
     switch( msg )
   {
        case WM_CREATE:
               GetClientRect( hWnd, &rect );
               hWndRichEdit = CreateWindowEx( WS_EX_CLIENTEDGE, "RichEdit20A", 0,
                                              WS_CHILD | WS_VISIBLE | ES_MULTILINE | WS_VSCROLL |
                                              WS_HSCROLL | ES_NOHIDESEL, 0, 0,
                                              rect.right - rect.left, rect.bottom - rect.top,
                                              hWnd, ( HMENU ) RichEditID, GetModuleHandle( NULL ), 0 );
           
           SendMessage( hWndRichEdit, EM_SETTYPOGRAPHYOPTIONS, TO_SIMPLELINEBREAK, TO_SIMPLELINEBREAK );
           if( ! SendMessage( hWndRichEdit, EM_GETTYPOGRAPHYOPTIONS, 1, 1 ) )
                    RichEditVersion = 2;
               else
                    RichEditVersion = 3;
                 
                 SendMessage( hWndRichEdit, EM_SETEDITSTYLE, SES_EMULATESYSEDIT, SES_EMULATESYSEDIT );
       
               OldWndProc = ( WNDPROC ) SetWindowLong( hWndRichEdit, GWL_WNDPROC, ( LONG ) NewRichEditProc );
               SendMessage( hWndRichEdit, EM_LIMITTEXT, -1, 0 );
           // SetColor();
               SendMessage( hWndRichEdit, EM_SETMODIFY, FALSE, 0 );
               SendMessage( hWndRichEdit, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS );
               SendMessage( hWndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0 );

           hFont  = CreateFont( 18, 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Courier New" );
           SendMessage( hWndRichEdit, WM_SETFONT, ( WPARAM ) hFont, 0 );

               FillHiliteInfo();
               SetFocus( hWndRichEdit );
               break;
               
        case WM_NOTIFY:
               if( ( ( NMHDR * ) lParam )->code == EN_MSGFILTER )
               {
              if( ( ( MSGFILTER * ) lParam )->msg == WM_RBUTTONDOWN )                                  
                      {
                         hPopup = GetSubMenu( GetMenu( hWnd ), 1 );
                         PrepareEditMenu( hPopup );
                         pt.x = LOWORD( lParam );
                         pt.y = HIWORD( lParam );
                         ClientToScreen( hWnd, &pt );
                         TrackPopupMenu( hPopup, TPM_LEFTALIGN | TPM_BOTTOMALIGN, pt.x, pt.y,
                                         NULL, hWnd, NULL );
              }
            }
            break;    
       
           case WM_INITMENUPOPUP:
            if( lParam == 0 )
            {
               if( FileOpened )
               {   
                          EnableMenuItem( ( HMENU ) wParam, IDM_OPEN,   MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_CLOSE,  MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_SAVE,   MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_SAVEAS, MF_ENABLED );
                     }
                     else
                     { 
                          EnableMenuItem( ( HMENU ) wParam, IDM_OPEN, MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_CLOSE, MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_SAVE, MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_SAVEAS, MF_GRAYED );
                       }  
                    }
                   
                    else if( lParam == 1 )  
                     PrepareEditMenu( ( HMENU ) wParam );
                 
                  else if( lParam == 2 )  
            {
               if( FileOpened )
               {
                  EnableMenuItem( ( HMENU ) wParam, IDM_FIND,     MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_FINDNEXT, MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_FINDPREV, MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_REPLACE,  MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_GOTOLINE, MF_ENABLED );
                       }
                       else
                       {
                          EnableMenuItem( ( HMENU ) wParam, IDM_FIND,     MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_FINDNEXT, MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_FINDPREV, MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_REPLACE,  MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_GOTOLINE, MF_GRAYED );
                       }
                    }
                    break;
               
                case WM_COMMAND:
                 if( ! lParam ) // menu commands
                 { 
                      switch( LOWORD( wParam ) )
                      {
                         case IDM_OPEN:
                         { 
                              memset( &ofn, 0, sizeof( ofn ) );
                              ofn.lStructSize = sizeof( ofn );
                              ofn.hwndOwner = hWnd;
                              ofn.hInstance = GetModuleHandle( NULL );
                              ofn.lpstrFilter = szFileFilter;
                              FileName[ 0 ] = 0;
                              ofn.lpstrFile = FileName;
                            ofn.nMaxFile = sizeof( FileName );
                              ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
                           
                              if( GetOpenFileName( &ofn ) )
                              { 
                                   if( ( hFile = CreateFile( FileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                                                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ) ) !=
                                                               INVALID_HANDLE_VALUE )
                                   {
                                        editstream.dwCookie = ( DWORD_PTR ) hFile;
                                        editstream.pfnCallback = StreamInProc;
                                        SendMessage( hWndRichEdit, EM_STREAMIN, SF_TEXT, ( LPARAM ) &editstream );
                                        SendMessage( hWndRichEdit, EM_SETMODIFY, FALSE, 0 );
                                        CloseHandle( hFile );
                                        FileOpened = TRUE;
                                     }
                                     else  
                                      MessageBox( hWnd, OpenFileFail, AppName, MB_OK | MB_ICONERROR );
                            }          
                     }
                     break

                   case IDM_CLOSE:
                        {
                                 if( CheckModifyState( hWnd ) )
                                        SetWindowText( hWndRichEdit, NULL );
                                     FileOpened = FALSE;
                                  }
                                  break;  

                   case IDM_SAVE:
                        {
                           if( ( hFile = CreateFile( FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                                                       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ) ) !=
                                                       INVALID_HANDLE_VALUE )
                           {                           
                                        editstream.dwCookie = ( DWORD_PTR ) hFile;
                                        editstream.pfnCallback = StreamOutProc;
                                        SendMessage( hWndRichEdit, EM_STREAMOUT, SF_TEXT, ( LPARAM ) &editstream );
                                        SendMessage( hWndRichEdit, EM_SETMODIFY, FALSE, 0 );
                                        CloseHandle( hFile );
                                     }  
                               else                  
                                        MessageBox( hWnd, OpenFileFail, AppName, MB_OK | MB_ICONERROR );
                                  }      
                                  break;

                   case IDM_COPY:
                                SendMessage( hWndRichEdit, WM_COPY, 0, 0 );
                                break;

                   case IDM_CUT:
                                SendMessage( hWndRichEdit, WM_CUT, 0, 0 );
                                break;
                       
                   case IDM_PASTE:
                                SendMessage( hWndRichEdit, WM_PASTE, 0, 0 );
                                break;
                       
                   case IDM_DELETE:
                                SendMessage( hWndRichEdit, EM_REPLACESEL, TRUE, 0 );
                                break;

                   case IDM_SELECTALL:
                        {
                           chrg.cpMin = 0;
                                   chrg.cpMax = -1;
                                   SendMessage( hWndRichEdit, EM_EXSETSEL, 0, ( LPARAM ) &chrg );
                                }
                                break;  

                   case IDM_UNDO:
                        SendMessage( hWndRichEdit, EM_UNDO, 0, 0 );
                        break;

                   case IDM_REDO:
                                SendMessage( hWndRichEdit, EM_REDO, 0, 0 );
                                break;

                   case IDM_OPTION:
                                DialogBoxParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_OPTIONDLG, hWnd, OptionProc, 0 );
                                break;

                   case IDM_SAVEAS:
                        {
                           RtlZeroMemory( &ofn, sizeof( ofn ) );
                                   ofn.lStructSize = sizeof( ofn );
                                   ofn.hwndOwner = hWnd;
                                   ofn.hInstance = GetModuleHandle( NULL );
                                   ofn.lpstrFilter = szFileFilter;
                                   AlternateFileName[ 0 ] = 0;
                                   ofn.lpstrFile = AlternateFileName;
                                   ofn.nMaxFile = sizeof( AlternateFileName );
                                   ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
                       
                                   if( GetSaveFileName( &ofn ) )
                                   {   
                              if( CreateFile( AlternateFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                                              CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ) !=
                                              INVALID_HANDLE_VALUE )
                              {
                              }             
                                       }
                                    }
                                    break;      

                   case IDM_FIND:
                        if( ! hSearch )
                                     CreateDialogParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_FINDDLG, hWnd, SearchProc, 0 );
                        break;

                   case IDM_REPLACE:
                        if( ! hSearch )
                           CreateDialogParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_REPLACEDLG, hWnd, ReplaceProc, 0 );
                        break;

                   case IDM_GOTOLINE:
                        if( ! hSearch )
                                     CreateDialogParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_GOTODLG, hWnd, GoToProc, 0 );
                        break;

                   case IDM_FINDNEXT:
                        if( lstrlen( FindBuffer ) )
                        {   
                                     SendMessage( hWndRichEdit, EM_EXGETSEL, 0, ( LPARAM ) &findtext.chrg );

                                     if( findtext.chrg.cpMin != findtext.chrg.cpMax )
                                          findtext.chrg.cpMin = findtext.chrg.cpMax;
                             
                                     findtext.chrg.cpMax = -1;
                                     findtext.lpstrText = FindBuffer;

                                     if( SendMessage( hWndRichEdit, EM_FINDTEXTEX, FR_DOWN, ( LPARAM ) &findtext ) != -1 )
                                        SendMessage( hWndRichEdit, EM_EXSETSEL, 0, ( LPARAM ) &findtext.chrgText );
                                  }
                                  break;      

                   case IDM_FINDPREV:
                        if( lstrlen( FindBuffer ) )
                        {   
                                     SendMessage( hWndRichEdit, EM_EXGETSEL, 0, ( LPARAM ) &findtext.chrg );
                             
                                     findtext.chrg.cpMax = 0;
                                     findtext.lpstrText = FindBuffer;
                             
                                     if( SendMessage( hWndRichEdit, EM_FINDTEXTEX, 0, ( LPARAM ) &findtext ) != -1 )
                                          SendMessage( hWndRichEdit, EM_EXSETSEL, 0, ( LPARAM ) &findtext.chrgText );
                                    }
                                    break;      

                   case IDM_EXIT:
                        SendMessage( hWnd, WM_CLOSE, 0, 0 );
                        break;
                }
             }  
             break;  
   
          case WM_CLOSE:
               if( CheckModifyState( hWnd ) )
               {
                    DeleteObject( hFont )
                      DestroyWindow( hWnd );
                   }  
                   break;
                 
          case WM_SIZE:
                 MoveWindow( hWndRichEdit, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );
                 break;    
   
          case WM_DESTROY:
                 PostQuitMessage( 0 );
                 break;
     }     
   return DefWindowProc( hWnd, msg, wParam, lParam );      
}  

#pragma argsused

int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show )
{
   WNDCLASSEX wc;
   MSG msg;
   HWND hWnd;
   char * szClassName = "FreshClass";
   HACCEL hAccel;
   HINSTANCE hDll = LoadLibrary( "riched32" );
   
   wc.cbSize = sizeof( WNDCLASSEX );
   wc.style  = CS_HREDRAW | CS_VREDRAW;
   wc.lpfnWndProc = WndProc;
   wc.cbClsExtra  = 0;
   wc.cbWndExtra  = 0;
   wc.hInstance   = hInstance;
   wc.hbrBackground = GetStockObject( WHITE_BRUSH );
   wc.lpszMenuName  = ( LPCTSTR ) IDR_MAINMENU;
   wc.lpszClassName = szClassName;
   wc.hIcon = wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
   wc.hCursor = LoadCursor( NULL, IDC_ARROW );
   RegisterClassEx( &wc );
   
   hWnd = CreateWindowEx( NULL, szClassName, "Fresh 1.0",
                          WS_OVERLAPPEDWINDOW, 70, 70,
                          1130, 630, 0, NULL, hInstance, NULL );
 
   ShowWindow( hWnd, SW_SHOWNORMAL );
   UpdateWindow( hWnd );
 
   hAccel = LoadAccelerators( hInstance, ( LPCTSTR ) IDR_MAINACCEL );
                 
     while( GetMessage( &msg, 0, 0, 0 ) )
     {
        if( IsDialogMessage( hSearch, &msg ) )
               TranslateAccelerator( hWnd, hAccel, &msg );
            else
            {
               TranslateMessage( &msg );
                 DispatchMessage( &msg );
            }
     }       

   FreeLibrary( hDll );

   return 0;
}


fresh.rc
Code: Select all  Expand view
// #include "resource.h"

#define IDC_NEXT                        1003
#define IDR_MAINMENU                    101
#define IDD_OPTIONDLG                   101
#define IDD_FINDDLG                     102
#define IDD_GOTODLG                     103
#define IDD_REPLACEDLG                  104
#define IDR_MAINACCEL                   105
#define IDC_BACKCOLORBOX                1000
#define IDC_FINDEDIT                    1000
#define IDC_TEXTCOLORBOX                1001
#define IDC_MATCHCASE                   1001
#define IDC_REPLACEEDIT                 1001
#define IDC_WHOLEWORD                   1002
#define IDC_DOWN                        1003
#define IDC_UP                          1004
#define IDC_LINENO                      1005
#define IDM_OPEN                        40001
#define IDM_SAVE                        40002
#define IDM_CLOSE                       40003
#define IDM_SAVEAS                      40004
#define IDM_EXIT                        40005
#define IDM_COPY                        40006
#define IDM_CUT                         40007
#define IDM_PASTE                       40008
#define IDM_DELETE                      40009
#define IDM_SELECTALL                   40010
#define IDM_OPTION                      40011
#define IDM_UNDO                        40012
#define IDM_REDO                        40013
#define IDM_FIND                        40014
#define IDM_FINDNEXT                    40015
#define IDM_REPLACE                     40016
#define IDM_GOTOLINE                    40017
#define IDM_FINDPREV                    40018

IDR_MAINMENU MENU DISCARDABLE
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "&Open",                       IDM_OPEN
        MENUITEM "&Close",                      IDM_CLOSE
        MENUITEM "&Save",                       IDM_SAVE
        MENUITEM "Save &As",                    IDM_SAVEAS
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                       IDM_EXIT
    END
    POPUP "&Edit"
    BEGIN
        MENUITEM "&Undo",                       IDM_UNDO
        MENUITEM "&Redo",                       IDM_REDO
        MENUITEM "&Copy",                       IDM_COPY
        MENUITEM "C&ut",                        IDM_CUT
        MENUITEM "&Paste",                      IDM_PASTE
        MENUITEM SEPARATOR
        MENUITEM "&Delete",                     IDM_DELETE
        MENUITEM SEPARATOR
        MENUITEM "Select &All",                 IDM_SELECTALL
    END
    POPUP "&Search"
    BEGIN
        MENUITEM "&Find...\tCtrl+F",            IDM_FIND
        MENUITEM "Find &Next\tF3",              IDM_FINDNEXT
        MENUITEM "Find &Prev.\tCtrl+F3",        IDM_FINDPREV
        MENUITEM "&Replace..\tCtrl+R",          IDM_REPLACE
        MENUITEM SEPARATOR
        MENUITEM "&Go To Line\tCtrl+G",         IDM_GOTOLINE
    END
    MENUITEM "Options",                     IDM_OPTION
END

IDD_OPTIONDLG DIALOG DISCARDABLE  0, 0, 183, 54
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION |
    WS_SYSMENU
CAPTION "Options"
FONT 8, "MS Sans Serif"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,137,7,39,14
    PUSHBUTTON      "Cancel",IDCANCEL,137,25,39,14
    GROUPBOX        "",IDC_STATIC,5,0,124,49
    LTEXT           "Background Color:",IDC_STATIC,20,14,60,8
    LTEXT           "",IDC_BACKCOLORBOX,85,11,28,14,SS_NOTIFY | WS_BORDER
    LTEXT           "Text Color:",IDC_STATIC,20,33,35,8
    LTEXT           "",IDC_TEXTCOLORBOX,85,29,28,14,SS_NOTIFY | WS_BORDER
END

IDD_FINDDLG DIALOG DISCARDABLE  0, 0, 186, 54
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Find.."
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDC_FINDEDIT,42,3,94,12,ES_AUTOHSCROLL
    CONTROL         "Match Case",IDC_MATCHCASE,"Button",BS_AUTOCHECKBOX |
                    WS_TABSTOP,6,24,54,10
    CONTROL         "Whole Word",IDC_WHOLEWORD,"Button",BS_AUTOCHECKBOX |
                    WS_TABSTOP,6,37,56,10
    CONTROL         "Down",IDC_DOWN,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
                    83,27,35,10
    CONTROL         "Up",IDC_UP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,83,
                    38,25,10
    DEFPUSHBUTTON   "OK",IDOK,141,3,39,12
    PUSHBUTTON      "Cancel",IDCANCEL,141,18,39,12
    LTEXT           "Find what:",IDC_STATIC,5,4,34,8
    GROUPBOX        "Direction",IDC_STATIC,70,18,64,32
END

IDD_GOTODLG DIALOGEX 0, 0, 106, 30
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Go To Line"
FONT 8, "MS Sans Serif", 0, 0
BEGIN
    EDITTEXT        IDC_LINENO,29,4,35,11,ES_AUTOHSCROLL | ES_NUMBER,
                    WS_EX_CLIENTEDGE
    DEFPUSHBUTTON   "OK",IDOK,70,4,31,11
    PUSHBUTTON      "Cancel",IDCANCEL,70,17,31,11
    LTEXT           "Line :",IDC_STATIC,8,5,18,8
END

IDD_REPLACEDLG DIALOG DISCARDABLE  0, 0, 186, 33
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Replace"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDC_FINDEDIT,51,3,84,12,ES_AUTOHSCROLL
    EDITTEXT        IDC_REPLACEEDIT,51,17,84,11,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "OK",IDOK,142,3,39,11
    PUSHBUTTON      "Cancel",IDCANCEL,142,17,39,11
    LTEXT           "Find what:",IDC_STATIC,3,4,34,8
    LTEXT           "Replace with",IDC_STATIC,3,18,42,8
END

IDR_MAINACCEL ACCELERATORS DISCARDABLE
BEGIN
    "F",            IDM_FIND,               VIRTKEY, CONTROL, NOINVERT
    "G",            IDM_GOTOLINE,           VIRTKEY, CONTROL, NOINVERT
    "R",            IDM_REPLACE,            VIRTKEY, CONTROL, NOINVERT
    VK_F3,          IDM_FINDNEXT,           VIRTKEY, NOINVERT
    VK_F3,          IDM_FINDPREV,           VIRTKEY, CONTROL, NOINVERT
END


go.bat:
Code: Select all  Expand view
set path=c:\bcc582\bin
brc32 -r fresh.rc
bcc32 -W fresh.c
if errorlevel 0 fresh


Usa un fichero wordfile.txt para indicar los tokens que resaltar:
Code: Select all  Expand view
[ASSEMBLY]
C1=CLASS ENDCLASS DATA METHOD INLINE
C2=#include #pragma #ifdef #endif #define another
C3=local static public private
C4=if else endif return do case end endcase
C5=
C6=
C7=
C8=
C9=
C10=


Ya funciona aunque no está completo y aún tiene algunos bugs al analizar las palabras. Pero el concepto está ahí y es muy interesante :-)

El código fuente original (en ensamblador) y la idea pertenecen a Iczelion@win32asm.cjb.net.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41332
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: RichEdit - Mejorando la velocidad de coloreado

Postby Antonio Linares » Tue Feb 28, 2012 10:03 pm

Version mejorada

fresh.c
Code: Select all  Expand view
#pragma resource "fresh.res"

#include <windows.h>
#include <richedit.h>
#include <stdio.h>

typedef struct
{
   DWORD    WordLen;    // the length of the word: used as a quick comparison
     char * pszWord;    // pointer to the word
     COLORREF * pColor; // point to the dword that contains the color used to hilite the word
     void * NextLink;   // point to the next WORDINFO structure
} WORDINFO;

#define IDR_MAINMENU               101
#define IDM_OPEN                 40001
#define IDM_SAVE                 40002
#define IDM_CLOSE                40003
#define IDM_SAVEAS               40004
#define IDM_EXIT                 40005
#define IDM_COPY                 40006
#define IDM_CUT                  40007
#define IDM_PASTE                40008
#define IDM_DELETE               40009
#define IDM_SELECTALL            40010
#define IDM_OPTION                   40011
#define IDM_UNDO                       40012
#define IDM_REDO                       40013
#define IDD_OPTIONDLG              101
#define IDC_BACKCOLORBOX          1000
#define IDC_TEXTCOLORBOX          1001
#define IDR_MAINACCEL              105
#define IDD_FINDDLG                102
#define IDD_GOTODLG                103
#define IDD_REPLACEDLG             104
#define IDC_FINDEDIT              1000
#define IDC_MATCHCASE             1001
#define IDC_REPLACEEDIT           1001
#define IDC_WHOLEWORD             1002
#define IDC_DOWN                  1003
#define IDC_UP                    1004
#define IDC_LINENO                1005
#define IDM_FIND                 40014
#define IDM_FINDNEXT             40015
#define IDM_REPLACE              40016
#define IDM_GOTOLINE             40017
#define IDM_FINDPREV             40018

#define RichEditID                     300

#define CLR_HRED      RGB( 255,   0,   0 )
#define CLR_HGREEN    RGB(   0, 255,   0 )
#define CLR_GREEN     RGB(   0, 128,   0 )
#define CLR_HBLUE     RGB(   0,   0, 255 )
#define CLR_YELLOW    RGB( 255, 255,   0 )
#define CLR_HCYAN     RGB(   0, 255, 255 )
#define CLR_BLACK     RGB(   0,   0,   0 )
#define CLR_WHITE     RGB( 255, 255, 255 )

char FindBuffer[ 256 ];
char ReplaceBuffer[ 256 ];
HWND hWndRichEdit;
WNDPROC OldWndProc;
int RichEditVersion;

COLORREF BackGroundColor = CLR_WHITE;
COLORREF TextColor = CLR_BLACK;
COLORREF CommentColor = CLR_HBLUE;
COLORREF ColorArray[ 10 ] = { CLR_HBLUE, CLR_GREEN, CLR_HCYAN, CLR_HBLUE, CLR_BLACK,
                                CLR_BLACK, CLR_BLACK, CLR_BLACK, CLR_BLACK, CLR_BLACK };  
BOOL FileOpened = FALSE;
char * szFileFilter = "PRG source code (*.prg)\0*.prg\0All Files (*.*)\0*.*\0";
char FileName[ 256 ];
char AlternateFileName[ 256 ];
HANDLE hSearch = NULL;
char * OpenFileFail = "Cannot open the file";
char * AppName = "Fresh 1.0";
char * WordFileName = "wordfile.txt";
FINDTEXTEX findtext;
char * WannaSave = "The data in the control is modified. Want to save it ?";
HFONT hFont;
WORDINFO SyntaxArray[ 256 ];

void SetColor( void )
{
     CHARFORMAT cfm;     
   
     SendMessage( hWndRichEdit, EM_SETBKGNDCOLOR, 0, BackGroundColor );
     memset( &cfm, 0, sizeof( cfm ) );
     cfm.cbSize = sizeof( cfm );
     cfm.dwMask = CFM_COLOR;
     cfm.crTextColor = TextColor;
     SendMessage( hWndRichEdit, EM_SETCHARFORMAT, SCF_ALL, ( LPARAM ) &cfm );
}

void CenterWindow( HWND hWnd )
{
   RECT rWnd, rDsk;
   LONG Left, Top, Width, Height;

   GetWindowRect( hWnd, &rWnd );
   GetWindowRect( GetDesktopWindow(), &rDsk );

   Width  = rWnd.right - rWnd.left;
   Height = rWnd.bottom - rWnd.top;
   Left   = ( rDsk.right / 2 ) - ( Width / 2 );
   Top    = ( rDsk.bottom / 2 ) - ( Height / 2 );

   MoveWindow( hWnd, Left, Top, Width, Height, FALSE );
}

void ParseBuffer( char * pszTokens, DWORD dwGroup )
{
   char * pStart;
   WORDINFO * pWordInfo;
   
   if( ! strlen( pszTokens ) )
      return;
       
   CharLower( pszTokens );
   
   while( * pszTokens )
   {
      while( * pszTokens == ' ' || * pszTokens == 9 && * pszTokens )
         pszTokens++;
         
      if( * pszTokens )
      { 
         pStart = pszTokens;

         while( * pszTokens != ' ' && * pszTokens != 9 && * pszTokens )
            pszTokens++;
         
         pWordInfo = SyntaxArray + pStart[ 0 ];

         if( SyntaxArray[ pStart[ 0 ] ].WordLen )
         {
            while( pWordInfo->NextLink )
               pWordInfo = pWordInfo->NextLink;    
               
            pWordInfo->NextLink = ( WORDINFO * ) malloc( sizeof( WORDINFO ) );  
            memset( ( void * ) pWordInfo->NextLink, 0, sizeof( WORDINFO ) );
            pWordInfo = pWordInfo->NextLink;
         }  

         pWordInfo->WordLen = pszTokens - pStart;
         pWordInfo->pszWord = ( char * ) malloc( pWordInfo->WordLen + 1 );
         strncpy( pWordInfo->pszWord, pStart, pWordInfo->WordLen );
         // pWordInfo->pszWord[ 0 ] = '*';
         // pWordInfo->pszWord[ pWordInfo->WordLen - 1 ] = '*';
         pWordInfo->pszWord[ pWordInfo->WordLen ] = 0;
         pWordInfo->pColor = ColorArray + dwGroup - 1;
         pWordInfo->NextLink = NULL;
         // MessageBox( 0, pWordInfo->pszWord, "token", 0 );
      }  
   }      
}   

void FillHiliteInfo( void )
{
   char filename[ 1024 ];
   char buffer[ 1024 ];
   char * pTemp;
   
   RtlZeroMemory( SyntaxArray, sizeof( SyntaxArray ) )

   GetModuleFileName( GetModuleHandle( NULL ), filename, sizeof( filename ) );
   pTemp = filename + lstrlen( filename );
   
   while( ( pTemp > filename ) && ( ( * pTemp ) != '\\' ) )
      pTemp--;
     
   * ++pTemp = 0;  
   lstrcat( pTemp, WordFileName );
   
   if( GetFileAttributes( filename ) != INVALID_FILE_ATTRIBUTES )
   {
      if( GetPrivateProfileString( "ASSEMBLY", "C1", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 1 );

      if( GetPrivateProfileString( "ASSEMBLY", "C2", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 2 );
         
      if( GetPrivateProfileString( "ASSEMBLY", "C3", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 3 );

      if( GetPrivateProfileString( "ASSEMBLY", "C4", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 4 );
         
      if( GetPrivateProfileString( "ASSEMBLY", "C5", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 5 );

      if( GetPrivateProfileString( "ASSEMBLY", "C6", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 6 );

      if( GetPrivateProfileString( "ASSEMBLY", "C7", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 7 );
         
      if( GetPrivateProfileString( "ASSEMBLY", "C8", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 8 );

      if( GetPrivateProfileString( "ASSEMBLY", "C9", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 9 );
         
      if( GetPrivateProfileString( "ASSEMBLY", "C10", NULL, buffer, sizeof( buffer ), filename ) )
         ParseBuffer( buffer, 10 );
   }  
   else
      MessageBox( 0, "wordfile.txt does not exist", "Attention", MB_ICONINFORMATION );                       
}  
   
BOOL CheckModifyState( HWND hWnd )
{
     int nResult;
     
   if( SendMessage( hWndRichEdit, EM_GETMODIFY, 0, 0 ) )
        if( ( nResult = MessageBox( hWnd, WannaSave, AppName, MB_YESNOCANCEL ) ) == IDYES )
               SendMessage( hWnd, WM_COMMAND, IDM_SAVE, 0 );
            else if( nResult == IDCANCEL )
               return FALSE;
                  
   return TRUE;
}

void PrepareEditMenu( HMENU hSubMenu )
{
   CHARRANGE chrg;

     if( ! SendMessage( hWndRichEdit, EM_CANPASTE, CF_TEXT, 0 ) )
        EnableMenuItem( hSubMenu, IDM_PASTE, MF_GRAYED );
     else  
          EnableMenuItem( hSubMenu, IDM_PASTE, MF_ENABLED );

     if( ! SendMessage( hWndRichEdit, EM_CANUNDO, 0, 0 ) )
        EnableMenuItem( hSubMenu, IDM_UNDO, MF_GRAYED );
     else  
          EnableMenuItem( hSubMenu, IDM_UNDO, MF_ENABLED );

     if( ! SendMessage( hWndRichEdit, EM_CANREDO, 0, 0 ) )
          EnableMenuItem( hSubMenu, IDM_REDO, MF_GRAYED );
     else
        EnableMenuItem( hSubMenu, IDM_REDO, MF_ENABLED );

     chrg.cpMin = SendMessage( hWndRichEdit, EM_EXGETSEL, 0, ( LPARAM ) &chrg );
     
     if( chrg.cpMin == chrg.cpMax )
     { 
        EnableMenuItem( hSubMenu, IDM_COPY,   MF_GRAYED );
          EnableMenuItem( hSubMenu, IDM_CUT,    MF_GRAYED );
          EnableMenuItem( hSubMenu, IDM_DELETE, MF_GRAYED );
     }   
     else
     { 
        EnableMenuItem( hSubMenu, IDM_COPY,   MF_ENABLED );
          EnableMenuItem( hSubMenu, IDM_CUT,    MF_ENABLED );
          EnableMenuItem( hSubMenu, IDM_DELETE, MF_ENABLED );
     }   
}

#pragma argsused

static INT_PTR CALLBACK OptionProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
   switch( wMsg )
   {
      case WM_INITDIALOG:
           CenterWindow( hDlg );
           return TRUE;

      case WM_COMMAND:
           switch( wParam )
           {
              case IDOK:
                   EndDialog( hDlg, IDOK );
                   break;

              case IDCANCEL:
                   EndDialog( hDlg, IDCANCEL );
                   break;
           }
           break;
   }
   return FALSE;
}

#pragma argsused

static INT_PTR CALLBACK SearchProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
   switch( wMsg )
   {
      case WM_INITDIALOG:
           CenterWindow( hDlg );
           return TRUE;

      case WM_COMMAND:
           switch( wParam )
           {
              case IDOK:
                   EndDialog( hDlg, IDOK );
                   break;

              case IDCANCEL:
                   EndDialog( hDlg, IDCANCEL );
                   break;
           }
           break;
   }
   return FALSE;
}

#pragma argsused

static INT_PTR CALLBACK ReplaceProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
   switch( wMsg )
   {
      case WM_INITDIALOG:
           CenterWindow( hDlg );
           return TRUE;

      case WM_COMMAND:
           switch( wParam )
           {
              case IDOK:
                   EndDialog( hDlg, IDOK );
                   break;

              case IDCANCEL:
                   EndDialog( hDlg, IDCANCEL );
                   break;
           }
           break;
   }
   return FALSE;
}

#pragma argsused

static INT_PTR CALLBACK GoToProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam )
{
   switch( wMsg )
   {
      case WM_INITDIALOG:
           CenterWindow( hDlg );
           return TRUE;

      case WM_COMMAND:
           switch( wParam )
           {
              case IDOK:
                   EndDialog( hDlg, IDOK );
                   break;

              case IDCANCEL:
                   EndDialog( hDlg, IDCANCEL );
                   break;
           }
           break;
   }
   return FALSE;
}

LRESULT WINAPI NewRichEditProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
   HDC hDC;
   HFONT hOldFont;
   RECT rect;
   TEXTRANGE txtrange;
   char buffer[ 1024 * 10 ];
   HRGN hRgn, hOldRgn;
   POINT pt;
   DWORD nChar, nLine, dwPos;
   WORDINFO * pWordInfo;
   BOOL bExit;

   switch( msg )
   {
      case WM_PAINT:       
           HideCaret( hWnd );
               CallWindowProc( OldWndProc, hWnd, msg, wParam, lParam );
               hDC = GetDC( hWnd );
               SetBkMode( hDC, TRANSPARENT );
               hOldFont = SelectObject( hDC, hFont );

               SendMessage( hWnd, EM_GETRECT, 0, ( LPARAM ) &rect );
               
             nChar = SendMessage( hWnd, EM_CHARFROMPOS, 0, ( LPARAM ) &rect );
               nLine = SendMessage( hWnd, EM_LINEFROMCHAR, nChar, 0 );
               txtrange.chrg.cpMin = SendMessage( hWnd, EM_LINEINDEX, nLine, 0 );
           txtrange.chrg.cpMax = SendMessage( hWnd, EM_CHARFROMPOS, 0, ( LPARAM ) &rect.right );               
               
               hRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom );
           hOldRgn = SelectObject( hDC, hRgn );

           txtrange.lpstrText = buffer;
           if( SendMessage( hWnd, EM_GETTEXTRANGE, 0, ( LPARAM ) &txtrange ) )
           {
              char * pPos = buffer;
              char * pStart = buffer;
              char * pToken;
             
              while( * pPos )
              {
                 if( * pPos == ' ' || * pPos == 9 || * pPos == 0xD || * pPos == 0xA )
                 {
                    pToken = ( char * ) malloc( pPos - pStart + 1 );
                    strncpy( pToken, pStart, pPos - pStart );
                    pToken[ pPos - pStart ] = 0;
                    // MessageBox( 0, pToken, "token", 0 );
                   
                    if( RichEditVersion == 3 )
                                   SendMessage( hWnd, EM_POSFROMCHAR, ( WPARAM ) &rect, ( LPARAM ) ( pStart - buffer ) + nChar );
                                else  
                                {   
                                 dwPos = SendMessage( hWnd, EM_POSFROMCHAR, ( WPARAM ) pStart, 0 );
                                   rect.left = LOWORD( dwPos );
                                   rect.top  = HIWORD( dwPos );
                                }
                               
                                if( pToken[ 0 ] >= '0' && pToken[ 0 ] <= '9' )
                                {   
                                   SetTextColor( hDC, CLR_HRED );   
                                   DrawText( hDC, pToken, -1, &rect, 0 );
                                }
                                else if( pToken[ 0 ] == '"' || pToken[ 0 ] == ''' )
                                {
                                   SetTextColor( hDC, CLR_YELLOW )
                                   DrawText( hDC, pToken, -1, &rect, 0 );
                                }      
                    else
                    {   
                                   if( pToken[ 0 ] >= 'A' && pToken[ 0 ] <= 'Z' )
                                      pWordInfo = SyntaxArray + pToken[ 0 ] - 'A' + 'a';
                                   else  
                                      pWordInfo = SyntaxArray + pToken[ 0 ];
                               
                                   bExit = FALSE;
                               
                                   while( pWordInfo->WordLen && ! bExit )
                                   {
                                      if( ( strlen( pToken ) == pWordInfo->WordLen ) &&
                                            ( lstrcmpi( pWordInfo->pszWord, pToken ) == 0 ) )
                                      { 
                                         bExit = TRUE;
                                         SetTextColor( hDC, * pWordInfo->pColor )
                                         DrawText( hDC, pToken, -1, &rect, 0 );  
                                      }
                                      else
                                      {
                                         if( pWordInfo->NextLink )
                                            pWordInfo= pWordInfo->NextLink;
                                         else
                                            bExit = TRUE;  
                                      }                
                                   }
                                }  
                                   
                    free( pToken );
                   
                    while( * pPos == ' ' || * pPos == 9 || * pPos == 0xD || * pPos == 0xA && * pPos )
                       pPos++;
                       
                    if( ! * pPos )
                       pPos++;   
                       
                    pStart = pPos;    
                 }  
                 pPos++;
              }  
           }  

           SelectObject( hDC, hOldRgn );
           DeleteObject( hRgn );
           SelectObject( hDC, hOldFont );
           ReleaseDC( hWnd, hDC );
           ShowCaret( hWnd );
           return 0;
   
      case WM_CLOSE:
             SetWindowLong( hWnd, GWL_WNDPROC, ( LONG ) OldWndProc );
             break;
   }
               
   return CallWindowProc( OldWndProc, hWnd, msg, wParam, lParam );
}

DWORD CALLBACK StreamInProc( DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR * pcb )
{      
     ReadFile( ( HANDLE ) dwCookie, ( LPVOID ) pbBuff, ( DWORD ) cb, ( LPDWORD ) pcb, 0 );
   return 0;
}  

DWORD CALLBACK StreamOutProc( DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG FAR * pcb )
{
     WriteFile( ( HANDLE ) dwCookie, ( LPVOID ) pbBuff, ( DWORD ) cb, ( LPDWORD ) pcb, 0 );
   return 0;
}  
    
LRESULT WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
     RECT rect;
   OPENFILENAME ofn;
     char buffer[ 256 ];
     EDITSTREAM editstream;
     FILE * hFile;
     HMENU hPopup;
     POINT pt;
     CHARRANGE chrg;
   
     switch( msg )
   {
        case WM_CREATE:
               GetClientRect( hWnd, &rect );
               hWndRichEdit = CreateWindowEx( WS_EX_CLIENTEDGE, "RichEdit20A", 0,
                                              WS_CHILD | WS_VISIBLE | ES_MULTILINE | WS_VSCROLL |
                                              WS_HSCROLL | ES_NOHIDESEL, 0, 0,
                                              rect.right - rect.left, rect.bottom - rect.top,
                                              hWnd, ( HMENU ) RichEditID, GetModuleHandle( NULL ), 0 );
           
           SendMessage( hWndRichEdit, EM_SETTYPOGRAPHYOPTIONS, TO_SIMPLELINEBREAK, TO_SIMPLELINEBREAK );
           if( ! SendMessage( hWndRichEdit, EM_GETTYPOGRAPHYOPTIONS, 1, 1 ) )
                    RichEditVersion = 2;
               else
                    RichEditVersion = 3;
                 
                 SendMessage( hWndRichEdit, EM_SETEDITSTYLE, SES_EMULATESYSEDIT, SES_EMULATESYSEDIT );
       
               OldWndProc = ( WNDPROC ) SetWindowLong( hWndRichEdit, GWL_WNDPROC, ( LONG ) NewRichEditProc );
               SendMessage( hWndRichEdit, EM_LIMITTEXT, -1, 0 );
           // SetColor();
               SendMessage( hWndRichEdit, EM_SETMODIFY, FALSE, 0 );
               SendMessage( hWndRichEdit, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS );
               SendMessage( hWndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0 );

           hFont  = CreateFont( 18, 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Courier New" );
           SendMessage( hWndRichEdit, WM_SETFONT, ( WPARAM ) hFont, 0 );

               FillHiliteInfo();
               SetFocus( hWndRichEdit );
               break;
               
        case WM_NOTIFY:
               if( ( ( NMHDR * ) lParam )->code == EN_MSGFILTER )
               {
              if( ( ( MSGFILTER * ) lParam )->msg == WM_RBUTTONDOWN )                                  
                      {
                         hPopup = GetSubMenu( GetMenu( hWnd ), 1 );
                         PrepareEditMenu( hPopup );
                         pt.x = LOWORD( lParam );
                         pt.y = HIWORD( lParam );
                         ClientToScreen( hWnd, &pt );
                         TrackPopupMenu( hPopup, TPM_LEFTALIGN | TPM_BOTTOMALIGN, pt.x, pt.y,
                                         NULL, hWnd, NULL );
              }
            }
            break;    
       
           case WM_INITMENUPOPUP:
            if( lParam == 0 )
            {
               if( FileOpened )
               {   
                          EnableMenuItem( ( HMENU ) wParam, IDM_OPEN,   MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_CLOSE,  MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_SAVE,   MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_SAVEAS, MF_ENABLED );
                     }
                     else
                     { 
                          EnableMenuItem( ( HMENU ) wParam, IDM_OPEN, MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_CLOSE, MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_SAVE, MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_SAVEAS, MF_GRAYED );
                       }  
                    }
                   
                    else if( lParam == 1 )  
                     PrepareEditMenu( ( HMENU ) wParam );
                 
                  else if( lParam == 2 )  
            {
               if( FileOpened )
               {
                  EnableMenuItem( ( HMENU ) wParam, IDM_FIND,     MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_FINDNEXT, MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_FINDPREV, MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_REPLACE,  MF_ENABLED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_GOTOLINE, MF_ENABLED );
                       }
                       else
                       {
                          EnableMenuItem( ( HMENU ) wParam, IDM_FIND,     MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_FINDNEXT, MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_FINDPREV, MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_REPLACE,  MF_GRAYED );
                          EnableMenuItem( ( HMENU ) wParam, IDM_GOTOLINE, MF_GRAYED );
                       }
                    }
                    break;
               
                case WM_COMMAND:
                 if( ! lParam ) // menu commands
                 { 
                      switch( LOWORD( wParam ) )
                      {
                         case IDM_OPEN:
                         { 
                              memset( &ofn, 0, sizeof( ofn ) );
                              ofn.lStructSize = sizeof( ofn );
                              ofn.hwndOwner = hWnd;
                              ofn.hInstance = GetModuleHandle( NULL );
                              ofn.lpstrFilter = szFileFilter;
                              FileName[ 0 ] = 0;
                              ofn.lpstrFile = FileName;
                            ofn.nMaxFile = sizeof( FileName );
                              ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
                           
                              if( GetOpenFileName( &ofn ) )
                              { 
                                   if( ( hFile = CreateFile( FileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                                                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ) ) !=
                                                               INVALID_HANDLE_VALUE )
                                   {
                                        editstream.dwCookie = ( DWORD_PTR ) hFile;
                                        editstream.pfnCallback = StreamInProc;
                                        SendMessage( hWndRichEdit, EM_STREAMIN, SF_TEXT, ( LPARAM ) &editstream );
                                        SendMessage( hWndRichEdit, EM_SETMODIFY, FALSE, 0 );
                                        CloseHandle( hFile );
                                        FileOpened = TRUE;
                                     }
                                     else  
                                      MessageBox( hWnd, OpenFileFail, AppName, MB_OK | MB_ICONERROR );
                            }          
                     }
                     break

                   case IDM_CLOSE:
                        {
                                 if( CheckModifyState( hWnd ) )
                                        SetWindowText( hWndRichEdit, NULL );
                                     FileOpened = FALSE;
                                  }
                                  break;  

                   case IDM_SAVE:
                        {
                           if( ( hFile = CreateFile( FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                                                       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ) ) !=
                                                       INVALID_HANDLE_VALUE )
                           {                           
                                        editstream.dwCookie = ( DWORD_PTR ) hFile;
                                        editstream.pfnCallback = StreamOutProc;
                                        SendMessage( hWndRichEdit, EM_STREAMOUT, SF_TEXT, ( LPARAM ) &editstream );
                                        SendMessage( hWndRichEdit, EM_SETMODIFY, FALSE, 0 );
                                        CloseHandle( hFile );
                                     }  
                               else                  
                                        MessageBox( hWnd, OpenFileFail, AppName, MB_OK | MB_ICONERROR );
                                  }      
                                  break;

                   case IDM_COPY:
                                SendMessage( hWndRichEdit, WM_COPY, 0, 0 );
                                break;

                   case IDM_CUT:
                                SendMessage( hWndRichEdit, WM_CUT, 0, 0 );
                                break;
                       
                   case IDM_PASTE:
                                SendMessage( hWndRichEdit, WM_PASTE, 0, 0 );
                                break;
                       
                   case IDM_DELETE:
                                SendMessage( hWndRichEdit, EM_REPLACESEL, TRUE, 0 );
                                break;

                   case IDM_SELECTALL:
                        {
                           chrg.cpMin = 0;
                                   chrg.cpMax = -1;
                                   SendMessage( hWndRichEdit, EM_EXSETSEL, 0, ( LPARAM ) &chrg );
                                }
                                break;  

                   case IDM_UNDO:
                        SendMessage( hWndRichEdit, EM_UNDO, 0, 0 );
                        break;

                   case IDM_REDO:
                                SendMessage( hWndRichEdit, EM_REDO, 0, 0 );
                                break;

                   case IDM_OPTION:
                                DialogBoxParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_OPTIONDLG, hWnd, OptionProc, 0 );
                                break;

                   case IDM_SAVEAS:
                        {
                           RtlZeroMemory( &ofn, sizeof( ofn ) );
                                   ofn.lStructSize = sizeof( ofn );
                                   ofn.hwndOwner = hWnd;
                                   ofn.hInstance = GetModuleHandle( NULL );
                                   ofn.lpstrFilter = szFileFilter;
                                   AlternateFileName[ 0 ] = 0;
                                   ofn.lpstrFile = AlternateFileName;
                                   ofn.nMaxFile = sizeof( AlternateFileName );
                                   ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
                       
                                   if( GetSaveFileName( &ofn ) )
                                   {   
                              if( CreateFile( AlternateFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
                                              CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ) !=
                                              INVALID_HANDLE_VALUE )
                              {
                              }             
                                       }
                                    }
                                    break;      

                   case IDM_FIND:
                        if( ! hSearch )
                                     CreateDialogParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_FINDDLG, hWnd, SearchProc, 0 );
                        break;

                   case IDM_REPLACE:
                        if( ! hSearch )
                           CreateDialogParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_REPLACEDLG, hWnd, ReplaceProc, 0 );
                        break;

                   case IDM_GOTOLINE:
                        if( ! hSearch )
                                     CreateDialogParam( GetModuleHandle( NULL ), ( LPCTSTR ) IDD_GOTODLG, hWnd, GoToProc, 0 );
                        break;

                   case IDM_FINDNEXT:
                        if( lstrlen( FindBuffer ) )
                        {   
                                     SendMessage( hWndRichEdit, EM_EXGETSEL, 0, ( LPARAM ) &findtext.chrg );

                                     if( findtext.chrg.cpMin != findtext.chrg.cpMax )
                                          findtext.chrg.cpMin = findtext.chrg.cpMax;
                             
                                     findtext.chrg.cpMax = -1;
                                     findtext.lpstrText = FindBuffer;

                                     if( SendMessage( hWndRichEdit, EM_FINDTEXTEX, FR_DOWN, ( LPARAM ) &findtext ) != -1 )
                                        SendMessage( hWndRichEdit, EM_EXSETSEL, 0, ( LPARAM ) &findtext.chrgText );
                                  }
                                  break;      

                   case IDM_FINDPREV:
                        if( lstrlen( FindBuffer ) )
                        {   
                                     SendMessage( hWndRichEdit, EM_EXGETSEL, 0, ( LPARAM ) &findtext.chrg );
                             
                                     findtext.chrg.cpMax = 0;
                                     findtext.lpstrText = FindBuffer;
                             
                                     if( SendMessage( hWndRichEdit, EM_FINDTEXTEX, 0, ( LPARAM ) &findtext ) != -1 )
                                          SendMessage( hWndRichEdit, EM_EXSETSEL, 0, ( LPARAM ) &findtext.chrgText );
                                    }
                                    break;      

                   case IDM_EXIT:
                        SendMessage( hWnd, WM_CLOSE, 0, 0 );
                        break;
                }
             }  
             break;  
   
          case WM_CLOSE:
               if( CheckModifyState( hWnd ) )
               {
                    DeleteObject( hFont )
                      DestroyWindow( hWnd );
                   }  
                   break;
                 
          case WM_SIZE:
                 MoveWindow( hWndRichEdit, 0, 0, LOWORD( lParam ), HIWORD( lParam ), TRUE );
                 break;    
   
          case WM_DESTROY:
                 PostQuitMessage( 0 );
                 break;
     }     
   return DefWindowProc( hWnd, msg, wParam, lParam );      
}  

#pragma argsused

int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show )
{
   WNDCLASSEX wc;
   MSG msg;
   HWND hWnd;
   char * szClassName = "FreshClass";
   HACCEL hAccel;
   HINSTANCE hDll = LoadLibrary( "riched32" );
   
   wc.cbSize = sizeof( WNDCLASSEX );
   wc.style  = CS_HREDRAW | CS_VREDRAW;
   wc.lpfnWndProc = WndProc;
   wc.cbClsExtra  = 0;
   wc.cbWndExtra  = 0;
   wc.hInstance   = hInstance;
   wc.hbrBackground = GetStockObject( WHITE_BRUSH );
   wc.lpszMenuName  = ( LPCTSTR ) IDR_MAINMENU;
   wc.lpszClassName = szClassName;
   wc.hIcon = wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
   wc.hCursor = LoadCursor( NULL, IDC_ARROW );
   RegisterClassEx( &wc );
   
   hWnd = CreateWindowEx( NULL, szClassName, "Fresh 1.0",
                          WS_OVERLAPPEDWINDOW, 70, 70,
                          1130, 630, 0, NULL, hInstance, NULL );
 
   ShowWindow( hWnd, SW_SHOWNORMAL );
   UpdateWindow( hWnd );
 
   hAccel = LoadAccelerators( hInstance, ( LPCTSTR ) IDR_MAINACCEL );
                 
     while( GetMessage( &msg, 0, 0, 0 ) )
     {
        if( IsDialogMessage( hSearch, &msg ) )
               TranslateAccelerator( hWnd, hAccel, &msg );
            else
            {
               TranslateMessage( &msg );
                 DispatchMessage( &msg );
            }
     }       

   FreeLibrary( hDll );

   return 0;
}


wordfile.txt
Code: Select all  Expand view
[ASSEMBLY]
C1=#include #pragma #ifdef #ifndef #else #endif #define
C2=CLASS ENDCLASS DATA CLASSDATA METHOD INLINE VIRTUAL SETGET ACCESS DEFAULT
C3=local static public private nil
C4=if else endif function return do case end otherwise endcase
C5=
C6=
C7=
C8=
C9=
C10=
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41332
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 13 guests