******************************************************************************** * Program : RICHEDIT.PRG * Launch RICHEDIT.EXE * Aim : Show how to program Applications using Windows traditional manner, * ..........: with NTKCORE GUI (low level) set of functions for X/HARBOUR. * ..........: RichEdit demonstration. * Make......: Juste type MK RICHEDIT * Date : 24/04/06 * Author(s) : Jn DECHEREUX * Copyright : (c) 2002-2006 - Jn DECHEREUX. Tous droits réservés/All Rights Reserved. ******************************************************************************** * Remark: * I have to confess that English is not mother tongue. So, in case of * typo or misspelling, don't be too angry - just bear with me. * You have to know that i'll do consider any comment, correction, suggestion * with great pleasure and high kindliness. Just be polite ! ;-) * This remark is also available for bug notifications or any other kind of * contributions that can improve my product... ******************************************************************************** #include "windows.ch" #include "ntkacc.ch" #include "ntkbtn.ch" #include "ntkcctrl.ch" #include "ntkcmdlg.ch" #include "ntkgdi.ch" #include "ntkimg.ch" #include "ntkmsg.ch" #include "ntkredit.ch" #include "ntkttips.ch" #include "wNtk.ch" #define CR CHR(13) #define ID_GET_RE 7000 #define ID_BTN_SETFONT 8000 #define ID_BTN_BKGCOLOR 8001 #define ID_BTN_PRINT 8002 //#define RICHEDIT_CLASS "RichEdit" // RichEdit v1.0. #define RICHEDIT_CLASS "RichEdit20A" // We want a RichEdit v2.0 minimum compatibility. For unicode just use "RichEdit20W". #define MSFTEDIT_CLASS "RICHEDIT50W" // We want a RichEdit v4.1 Static hLibRichEdit Static hInst Static hGet0 Static hBtn0, hBtn1, hBtn2, hBtn3 FUNCTION MAIN() LOCAL cMsg LOCAL NTK_aMSG := { 0,0,0,0,0,0,0 } // 7 elements, see NTKMSG.CH LOCAL hInst := NTK_GetInstance() LOCAL hIcon := NTK_LoadIcon( Nil , IDI_HAND ) // IDI_APPLICATION) LOCAL hCurs := NTK_LoadCursor( Nil , IDC_ARROW) LOCAL hBrush := NTK_GetStockObject(WHITE_BRUSH) //LTGRAY_BRUSH) LOCAL cWinTitle := "RichEdit demo with NTKCore for [x]Harbour" LOCAL cClassName := "NTKRichEditRTFApp" LOCAL hWndDemo hInst := NTK_GetInstance() IF !NTK_RegisterClassEx( CS_HREDRAW + CS_VREDRAW,; hInst,; hIcon,; hCurs,; hBrush,; cClassName,; { |hWnd, message, nwParam, nlParam|; MAINWNDPROC(hWnd, message, nwParam, nlParam) } ) NTK_MsgBox( , "Can't register NTKFEN class..." ) RETURN Nil ENDIF hWndDemo = NTK_CreateWindowEx( WS_EX_CLIENTEDGE, cClassName, cWinTitle, ; WS_SYSMENU,; CW_USEDEFAULT, CW_USEDEFAULT,; CW_USEDEFAULT, CW_USEDEFAULT,; NULL, NULL, hInst, NULL) IF hWndDemo == 0 NTK_MsgBox( , "Can not create Window..." ) RETURN Nil ENDIF NTK_ShowWindow( hWndDemo, SW_SHOW ) NTK_UpdateWindow( hWndDemo ) // ---------------------------------- NTK's Main Events (Windows Msg) Loop DO WHILE NTK_GetMessage( NTK_aMSG ) //,hWndDemo,0,0 ) NTK_TranslateMessage( NTK_aMSG ) NTK_DispatchMessage( NTK_aMSG ) ENDDO IF ( NTK_MsgBox(hWndDemo, "Do you want to save changes into RicheEdit.Rtf, before exit ?", "Save changes ?", MB_ICONQUESTION+MB_YESNO) ) == IDYES NTK_RE_SaveRtfFile( hGet0, "RichEdit.Rtf") NTK_MsgBox( hWndDemo, "Done!", "Save changes", MB_ICONINFORMATION ) ENDIF NTK_DestroyWindow( hGet0 ) FreeLibrary( hLibRichEdit ) NTK_SelectWindow( hWndDemo ) NTK_DestroyWindow( hWndDemo ) NTK_UnregisterClass( cClassName, hInst ) RETURN ****** ****** ****** FUNCTION MAINWNDPROC( hWnd, message, nwParam, nlParam) LOCAL aPS := { 0,.T.,0,0,0,0,.T.,.T.,nil } // 9 elements, see NTKGDI.CH LOCAL hDC LOCAL nNotifyCode, nCtlID, hWndCtl, nPrevProc DO CASE CASE message == WM_CREATE **hLibRichEdit := NTK_LoadLibrary( "Riched20.dll") hLibRichEdit := NTK_LoadLibrary( "msftedit.dll") hGet0 := CreateRichEdit( hWnd, 10,60, __NTKMaxCol(hWnd)-20, __NTKMaxRow(hWnd)-60-20, hInst ) IF Empty(hGet0) NTK_MsgBox( hWnd, "Error creating RichEdit Control...", "We've got a problem!",MB_TOPMOST ) ELSE NTK_SetFocus(hGet0) ENDIF hBtn0 := NTK_CreateWindowEx( WS_EX_WINDOWEDGE,; "BUTTON", ; // window class "set &Font..." , ; // Button Title WS_CHILD ; // child window + WS_VISIBLE ; // - that can be seen + WS_TABSTOP ; // ... + BS_PUSHBUTTON, ; // - a normal PushButton 10, 05, ; // x,y position 120, 40, ; // width, height hWnd, ; // parent window ID_BTN_SETFONT, ; // id for child control to use Nil) // app instance hBtn1 := NTK_CreateWindowEx( WS_EX_WINDOWEDGE,; "BUTTON", ; // window class " Bkg &Color...",; // Button Title WS_CHILD ; // child window + WS_VISIBLE ; // - that can be seen + WS_TABSTOP ; // ... + BS_PUSHBUTTON, ; // - a normal PushButton 140, 05, ; // x,y position 120, 40, ; // width, height hWnd, ; // parent window ID_BTN_BKGCOLOR, ; // id for child control to use Nil) // app instance hBtn2 := NTK_CreateWindowEx( WS_EX_WINDOWEDGE,; "BUTTON", ; // window class " &Print..." ,; // Button Title WS_CHILD ; // child window + WS_VISIBLE ; // - that can be seen + WS_TABSTOP ; // ... + BS_PUSHBUTTON, ; // - a normal PushButton 270, 05, ; // x,y position 120, 40, ; // width, height hWnd, ; // parent window ID_BTN_PRINT, ; // id for child control to use Nil) // app instance RETURN(0) // According to M$ Win32 SDK Doc. We tell Windows we've processed the message CASE message == WM_SYSCOMMAND IF nwParam == SC_CLOSE // system menu double click, or Alt-F4 IF NTK_MsgBox( hWnd,; "Do you really want to quit ?",; "Your Attention Please !",; MB_OKCANCEL+MB_ICONQUESTION ) == IDOK NTK_PostQuitMessage(0) ENDIF RETURN(0) // According to M$ Win32 SDK Doc. We tell Windows we've processed the message ENDIF CASE message == WM_COMMAND nNotifyCode = NTK_HiWord(nwParam) // notification code (See BN_* in Windows.ch) nCtlID = NTK_LoWord(nwParam) // item, control, or accelerator identifier hWndCtl = nlParam // handle of control If nCtlID == ID_BTN_SETFONT // ------------- User has invoked the ChooseFont dialog SetFontRE( hGet0 ) ElseIf nCtlID == ID_BTN_BKGCOLOR // ------------- User has invoked the ChooseColor dialog SetBkgColorRE( hGet0 ) ElseIf nCtlID == ID_BTN_PRINT // ------------- User has invoked the Print button PrintRE(hWnd, hGet0) Endif RETURN(0) // According to M$ Win32 SDK Doc. We tell Windows we've processed the message CASE message == WM_PAINT hDC := NTK_BEGINPAINT( hWnd, aPS ) NTK_TextOut( hDC, __NTKMaxCol()-200, 45, "This is a RicheEdit control." ) NTK_ENDPAINT( hWnd, aPS ) RETURN(0) CASE message == WM_DESTROY NTK_PostQuitMessage(0) RETURN(0) ENDCASE RETURN( NTK_DEFWNDPROC(hWnd, message, nwParam, nlParam) ) //RETURN -1 // OR NTK_DEFWNDPROC( ... ) is the same ! ****** ****************************************************************************************** ****** ****** ****** STATIC FUNCTION SetBkgColorRE( hRichEdit ) local aChFmt := ARRAY( CHARFORMAT2_LENGTH ) LOCAL nFontBgClr := NTK_ChooseColor() IF nFontBgClr == -1 // ** user cancelled or an error has occured... NTK_SetFocus(hRichEdit) RETURN( .F. ) ENDIF // ** NTK_MsgBox( nil, Str(nFontBgClr), "The chosen colour is:", MB_OK+MB_ICONASTERISK+MB_TOPMOST ) // --- RETRIEVES THE CURRENT FORMATING ATTRIBUTES OF THE SELECTED TEXT If .NOT. ( NTK_RE_GetCharFormat(hRichEdit, aChFmt, SCF_SELECTION) ) // SCF_SELECTION or SCF_DEFAULT // ** an error has occured... NTK_SetFocus(hRichEdit) RETURN( .F. ) EndIf // -- Sets the new color background text propertie of aChFmt... aChFmt[ CHARFORMAT2_crBackColor ] := nFontBgClr // NTK_Rgb(nR,nG,nB) // --- (RE)DEFINES THE CURRENT FORMATING ATTRIBUTES OF THE SELECTED TEXT, USING aChFmt PROPERTIES... NTK_RE_SetCharFormat( hRichEdit, aChFmt, SCF_SELECTION ) // SCF_SELECTION or SCF_ALL NTK_SetFocus(hRichEdit) RETURN( .T. ) ****** ****** ****** STATIC FUNCTION SetFontRE(hRichEdit) local nFontFgClr, nFontBgClr local aFontTxt := ARRAY( FONT_LENGTH ) // 14 local aChFmtOrg := ARRAY( CHARFORMAT2_LENGTH ) local aChFmtNew := ARRAY( CHARFORMAT2_LENGTH ) // --- RETRIEVES THE CURRENT FORMATING ATTRIBUTES OF THE SELECTED TEXT If .NOT. ( NTK_RE_GetCharFormat(hRichEdit, aChFmtOrg, SCF_SELECTION) ) // SCF_SELECTION or SCF_DEFAULT nFontFgClr := NTK_RGB(255,0,255) nFontBgClr := NTK_RGB(255,255,128) aFontTxt := { -12,08,0,0,700, .F., .F., .F., 1, 0, 0, 0, 0, "COURIER NEW" } NTK_SetFocus(hRichEdit) RETURN( .F. ) Else // **NTK_MsgBox( nil, aChFmtOrg[ CHARFORMAT2_szFaceName ], "aChFmtOrg:", MB_TOPMOST ) nFontFgClr := aChFmtOrg[ CHARFORMAT2_crTextColor ] nFontBgClr := aChFmtOrg[ CHARFORMAT2_crBackColor ] aFontTxt := ARRAY( FONT_LENGTH ) // 14 aFontTxt[ _nHeight ] := aChFmtOrg[ CHARFORMAT2_yHeight ] / 20 // remember: in twips (1/1440 of an inch, or 1/20 of a printer's point). aFontTxt[ _nWidth ] := 08 aFontTxt[ nEscapement ] := 0 aFontTxt[ nOrientation ] := 0 aFontTxt[ fnWeight ] := IIF( NTK_AND(CFE_BOLD,aChFmtOrg[ CHARFORMAT2_dwEffects ]) >0, FW_BOLD, FW_NORMAL ) aFontTxt[ fdwItalic ] := IIF( NTK_AND(CFE_ITALIC, aChFmtOrg[ CHARFORMAT2_dwEffects ]) >0, .T., .F. ) aFontTxt[ fdwUnderline ] := IIF( NTK_AND(CFE_UNDERLINE, aChFmtOrg[ CHARFORMAT2_dwEffects ]) >0, .T., .F. ) aFontTxt[ fdwStrikeOut ] := IIF( NTK_AND(CFE_STRIKEOUT, aChFmtOrg[ CHARFORMAT2_dwEffects ]) >0, .T., .F. ) aFontTxt[ fdwCharSet ] := aChFmtOrg[ CHARFORMAT2_bCharSet ] aFontTxt[ fdwOutputPrecision ] := 0 aFontTxt[ fdwClipPrecision ] := 0 aFontTxt[ fdwQuality ] := 0 aFontTxt[ fdwPitchAndFamily ] := aChFmtOrg[ CHARFORMAT2_bPitchAndFamily ] aFontTxt[ lpszFace ] := aChFmtOrg[ CHARFORMAT2_szFaceName ] EndIf // ---- DISPLAYS & INITIALIZES THE USER DIALOG FONTS if (aFontTxt := NTK_ChooseFont(aFontTxt, , , @nFontFgClr)) == nil // NTK_MessageBox( , "User cancelled or an error has occured!", "NTK_ChooseFont()", MB_ICONEXCLAMATION+MB_OK+MB_TOPMOST ) NTK_SetFocus(hRichEdit) RETURN( nil ) endif // ---- SETTING aChFmtNew PROPERTIES FROM aFontTxt USER CHOICES aChFmtNew[ CHARFORMAT2_dwMask ] := CFM_CHARSET + CFM_FACE + CFM_SIZE + CFM_COLOR + CFM_BACKCOLOR + CFM_BOLD + CFM_ITALIC + CFM_UNDERLINE + CFM_STRIKEOUT // + CFM_WEIGHT aChFmtNew[ CHARFORMAT2_dwEffects ] := IIF( aFontTxt[ fdwItalic ] >0, CFE_ITALIC , 0 ) +; // CFE_BOLD IIF( aFontTxt[ fdwUnderline] >0, CFE_UNDERLINE, 0 ) +; IIF( aFontTxt[ fdwStrikeOut ]>0, CFE_STRIKEOUT, 0 ) +; IIF( aFontTxt[ fnWeight ] >=FW_BOLD, CFE_BOLD , 0 ) aChFmtNew[ CHARFORMAT2_yHeight ] := aFontTxt[ _nHeight ] * 20 // remember: in twips (1/1440 of an inch, or 1/20 of a printer's point). aChFmtNew[ CHARFORMAT2_yOffset ] := Nil aChFmtNew[ CHARFORMAT2_crTextColor ] := nFontFgClr // NTK_Rgb(nR,nG,nB) aChFmtNew[ CHARFORMAT2_bCharSet ] := aFontTxt[ fdwCharSet ] // ANSI_CHARSET // OEM_CHARSET // DEFAULT_CHARSET aChFmtNew[ CHARFORMAT2_bPitchAndFamily ] := aFontTxt[ fdwPitchAndFamily ] // DEFAULT_PITCH aChFmtNew[ CHARFORMAT2_szFaceName ] := aFontTxt[ lpszFace ] // Times New Roman aChFmtNew[ CHARFORMAT2_wWeight ] := aFontTxt[ fnWeight ] // FW_ULTRABOLD aChFmtNew[ CHARFORMAT2_sSpacing ] := Nil aChFmtNew[ CHARFORMAT2_crBackColor ] := nFontBgClr // NTK_Rgb(nR,nG,nB) aChFmtNew[ CHARFORMAT2_lcid ] := Nil aChFmtNew[ CHARFORMAT2_dwReserved ] := 0 aChFmtNew[ CHARFORMAT2_sStyle ] := Nil aChFmtNew[ CHARFORMAT2_wKerning ] := Nil aChFmtNew[ CHARFORMAT2_bUnderlineType ] := Nil aChFmtNew[ CHARFORMAT2_bAnimation ] := Nil aChFmtNew[ CHARFORMAT2_bRevAuthor ] := Nil // --- (RE)DEFINES THE CURRENT FORMATING ATTRIBUTES OF THE SELECTED TEXT, USING aChFmtNew PROPERTIES... NTK_RE_SetCharFormat( hRichEdit, aChFmtNew, SCF_SELECTION ) // SCF_SELECTION or SCF_ALL NTK_SetFocus(hRichEdit) RETURN( .T. ) ****** ****** ****** STATIC FUNCTION PrintRE(hWndP, hRichEdit) local aPrintDlg := ARRAY( PD_Length ) local hPrinterDC // set up initial values for the printer dialog aPrintDlg[ PD_hwndOwner ] := hRichEdit aPrintDlg[ PD_nFlags ] := PD_RETURNDC // + PD_RETURNDEFAULT // this is also the default nlRet := NTK_PrintDlg( aPrintDlg ) // More configurable and more powerful way of doing things... IF nlRet==NIL .OR. !nlRet NTK_MsgBox( nil, "Cancelled by the user.", "Infos!", MB_OK+MB_ICONEXCLAMATION+MB_TOPMOST ) RETURN( .F. ) ENDIF hPrinterDC := aPrintDlg[ PD_hDC ] IF !NTK_RE_PrintRTF(hRichEdit, hPrinterDC ) NTK_MsgBox( nil, "Cannot print current RicheEdit...", "An error has occured!", MB_OK+MB_ICONEXCLAMATION+MB_TOPMOST ) RETURN( .F. ) ENDIF NTK_DeleteDC( hPrinterDC ) NTK_SetFocus(hRichEdit) RETURN( .T. ) ****** ****** ****** ****** ****** CreateRichEdit( hWndP, nX, nY, nWidth, nHeight, hInst ) ****** hWndP // Dialog box handle. ****** nX // Location. ****** nY ****** nWidth // Dimensions. ****** nHeight ****** hInst // Application or DLL instance. ****** FUNCTION CreateRichEdit( hWndP, nX, nY, nWidth, nHeight, hInst ) LOCAL hRichEdit LOCAL REOptions := ECO_AUTOVSCROLL + ECO_AUTOHSCROLL + ECO_NOHIDESEL + ECO_SAVESEL + ECO_SELECTIONBAR *hRichEdit := NTK_CreateWindowEx(0, RICHEDIT_CLASS, "Type your text from here..." ,; * ES_MULTILINE+WS_VISIBLE+WS_CHILD+WS_BORDER+WS_TABSTOP ,; * nX, nY, nWidth, nHeight ,; * hWndP, Nil, hInst, Nil) hRichEdit := NTK_CreateWindowEx(0, MSFTEDIT_CLASS , "Type your text from here..." ,; ES_MULTILINE+WS_VISIBLE+WS_CHILD+WS_BORDER+WS_TABSTOP+WS_VSCROLL ,; nX, nY, nWidth, nHeight ,; hWndP, Nil, hInst, Nil) // -- Set the control to accept the maximum amount of text NTK_SendMessage(hRichEdit, EM_LIMITTEXT, -1, 0) *$// -- Set Other options for the control *$NTK_SendMessage(hRichEdit, EM_SETOPTIONS, ECOOP_OR, REOptions) // -- Set the contol to automatically detect URLs NTK_SendMessage( hRichEdit, EM_AUTOURLDETECT, .T., 0) // -- Set the event masks for the rich edit control NTK_SendMessage(hRichEdit, EM_SETEVENTMASK, 0, ENM_SELCHANGE + ENM_LINK + ENM_KEYEVENTS ) // Set default text or Load Text from the RTF File into the RichEdit control IF !( NTK_RE_LoadRtfFile( hRichEdit, "RichEdit.Rtf") ) NTK_MessageBox( hWndP, "Cannot load related 'RichEdit.Rtf' file", "RTF Loading Error !", MB_OK+MB_ICONEXCLAMATION) **// Set Text for RE Control sample, has to be in RTF format **cREText := "{\\rtf1 NTK's Richedit 50W by Jn Dechereux Copyright" +; ** " (C) 2005\\par http://www.ntk.sis-log.com/tjs \\par" +; ** "{\\field{\\*\\fldinst{HYPERLINK mailto:jim@dunnes.net" +; ** " }}{\\fldrslt{\\cf1\\ul jnd@sis-log.com}}}}"; // Set Text for RE Control sample in standard ASCII format cREText := "NTK's Richedit sample by Jn Dechereux Copyright" +CR+; " (C) 2005 by http://www.ntk.sis-log.com" +CR+; "mailto:info_ntk@sis-log.com" +CR+; "mailto:jnd@sis-log.com" NTK_SendMessage(hRichEdit, WM_SETTEXT, 0, cREText) ENDIF //Set the caret selection to the end of any current text **NTK_SendMessage( hRichEdit, EM_SETSEL, -1, -1) /* aChFmt := ARRAY( CHARFORMAT2_LENGTH ) //aChFmt[ CHARFORMAT2_dwMask ] := CFM_CHARSET + CFM_FACE + CFM_SIZE + CFM_COLOR + CFM_BACKCOLOR + CFM_BOLD + CFM_ITALIC + CFM_UNDERLINE // + CFM_WEIGHT aChFmt[ CHARFORMAT2_dwMask ] := CFM_FACE + CFM_SIZE + CFM_COLOR + CFM_BACKCOLOR + CFM_BOLD + CFM_ITALIC + CFM_UNDERLINE // + CFM_WEIGHT aChFmt[ CHARFORMAT2_dwEffects ] := nil // CFE_BOLD aChFmt[ CHARFORMAT2_yHeight ] := 18 * 20 // remember: in twips (1/1440 of an inch, or 1/20 of a printer's point). aChFmt[ CHARFORMAT2_yOffset ] := Nil aChFmt[ CHARFORMAT2_crTextColor ] := NTK_RGB(255,0,255) **aChFmt[ CHARFORMAT2_bCharSet ] := ANSI_CHARSET // OEM_CHARSET // DEFAULT_CHARSET **aChFmt[ CHARFORMAT2_bPitchAndFamily ] := DEFAULT_PITCH //aChFmt[ CHARFORMAT2_szFaceName ] := "Courier New" // "Times New Roman" aChFmt[ CHARFORMAT2_szFaceName ] := "PlayBill" // "Courier New" aChFmt[ CHARFORMAT2_wWeight ] := Nil // FW_ULTRABOLD aChFmt[ CHARFORMAT2_sSpacing ] := Nil aChFmt[ CHARFORMAT2_crBackColor ] := NTK_RGB(255,255,128) aChFmt[ CHARFORMAT2_lcid ] := Nil aChFmt[ CHARFORMAT2_dwReserved ] := 0 aChFmt[ CHARFORMAT2_sStyle ] := Nil aChFmt[ CHARFORMAT2_wKerning ] := Nil aChFmt[ CHARFORMAT2_bUnderlineType ] := Nil aChFmt[ CHARFORMAT2_bAnimation ] := Nil aChFmt[ CHARFORMAT2_bRevAuthor ] := Nil NTK_RE_SetCharFormat( hRichEdit, aChFmt, SCF_ALL ) // SCF_SELECTION or SCF_ALL */ RETURN(hRichEdit) ****** ****** ******