****************************************************************************** * Program : TABCTRL.PRG * Launch TABCTRL.EXE * ..........: Show how to make Tab Controls with NTKRad. * Make : MKRAD TABCTRL * Date : 09/01/07 * Author(s) : Jn DECHEREUX * Copyright : (c) 2007 - Jn DECHEREUX. Tous droits réservés/All Rights Reserved. ******************************************************************************** // -- Manifest Windows XP // #define ISOLATION_AWARE_ENABLED 1 // remove remarks if you want fancy XP Theme buttons. #include "windows.ch" #include "ntkcctrl.ch" #include "ntkgdi.ch" #include "ntkmsg.ch" #include "ntkacc.ch" #include "ntkbtn.ch" #include "ntkcmd.ch" #include "ntkcmdEx.ch" #include "ntkedget.ch" #include "wNtk.ch" #include "wNtkKeys.ch" #include "ntkbtn.ch" #include "ntkimg.ch" #include "ntknetw.ch" #define CR CHR(13) #define ID_GET_1 7001 #define ID_GET_2 7002 #define ID_GET_3 7003 #define ID_BTN0 8000 #define ID_BTN_APPLY 8010 #define ID_PAGE1 8201 #define ID_PAGE2 8202 #define ID_PAGE3 8203 #define ID_TABCTRL1 10001 #Define PI_Id 1 #Define PI_hWnd 2 STATIC aPageInfo STATIC oB1, oB2 GLOBAL lExitPage3 := .F. FUNCTION MAIN() LOCAL hWndDemo LOCAL cWinTitle := "TAB Controls with NTKrad..." LOCAL oMyTab, nPage PRIVATE aBtnList := {} // Do not forget it! CREATE WINDOW hWndDemo ; TITLE cWinTitle ; // Minimum declaration AT 0,0 SIZE 450,400 ; ON PAINT DoRePaint() ; ON EXIT DoExit() // ----- Ensure that the common control dynamic-link library (DLL) is loaded. // ----- Don't forget to use this command if U plan to use controls such as DatePicker, tooltips... NTK_InitCommonControlsEx( ICC_DATE_CLASSES + ICC_BAR_CLASSES + ICC_STANDARD_CLASSES + ICC_WIN95_CLASSES ) // ------ Databases opening SELECT 1 USE ("PRODUCT.DBF") SHARE ALIAS products SELECT 2 USE ("ARTICLE.DBF") SHARE ALIAS articles // -------- A STANDARD WINDOWS BUTTON USING NEW XP THEME (if MANIFEST is activated in the .RC resource file) @ 310,010 BUTTON "&Quit (Esc)" SIZE 40,120 ; ID ID_BTN0 ; SUPER ACCEL KEY K_ESC ; ACTION NTK_SendCloseEvent(hWndDemo) ; // Tell NTK RAD system to call the ON EXIT proc. STATE NTK_BT_ENABLE ; FONT NTK_GetStockObject(SYSTEM_FONT) ; OF hWndDemo ; MESSAGE "This is a classic button using a manifest (new enhanced XP style)!" // -------- MAKE A NTKRAD's TAB CONTROL OBJECT -------------- lExitPage3 := .F. aPageInfo := { {nil,nil}, {nil,nil}, {nil,nil} } // For each page we keep trace of both: [nPageID,hWndPage] @ 075,010 TO 275,430 TABCONTROL oMyTab ; TABHEIGHT 30 ; INTO hWndDemo ; ID ID_TABCTRL1 ; START AT ID_PAGE2 ; ON PAGE DoPageManager(oMyTab) ADD PAGE TO oMyTab ID ID_PAGE1 LABEL "&Product List" ; SUPER ACCEL KEY K_ALT_P ; BITMAP UP "LOUPE_UP" ; BITMAP DN "LOUPE_DN" ; BITMAP OVER "LOUPE_OVR" ; BITMAP GRAYED "LOUPE_OFF" ; TOOLTIP "Go to 1st page..." ADD PAGE TO oMyTab ID ID_PAGE2 LABEL "&Article List" ; SUPER ACCEL KEY K_ALT_A ; BITMAP UP "LOUPE_UP" ; BITMAP DN "LOUPE_DN" ; BITMAP OVER "LOUPE_OVR" ; BITMAP GRAYED "LOUPE_OFF" ; TOOLTIP "Go to 2nd page..." ADD PAGE TO oMyTab ID ID_PAGE3 LABEL "&Edit article" ; SUPER ACCEL KEY K_ALT_E ; BITMAP UP "LOUPE_UP" ; BITMAP DN "LOUPE_DN" ; BITMAP OVER "LOUPE_OVR" ; BITMAP GRAYED "LOUPE_OFF" ; TOOLTIP "Go to 3rd page..." // We decided to start on Page ID_PAGE2, so we just do it! DoInitPage2(oMyTab) // ---------------------------------------------------------- ACTIVATE WINDOW hWndDemo NORMAL // Display window and its controls NTK_SetFocus(oB2:hWnd) AUTO HANDLE EVENTS OF WINDOW hWndDemo USING ; // Start background processing BUTTON LIST aBtnList // ----------- Do not forget to release unused objects before exiting the program ! FOR nPage := 1 TO LEN(aPageInfo) IF !EMPTY(aPageInfo[nPage, PI_hWnd]) CLOSE WINDOW aPageInfo[nPage, PI_hWnd] ENDIF NEXT CLOSE DATABASES CLOSE WINDOW hWndDemo RETURN // End running NTK RAD application. ****** ****** ****** FUNCTION DoExit(hWnd, message, nwParam, nlParam) // This proc. is automatically called each time our window receives a Destroy Msg or // when NTK_SendCloseEvent() is invoked... IF NTK_MsgBox( hWnd,; "Do you really want to quit ?",; "Tab Controls",; MB_OKCANCEL+MB_ICONQUESTION ) == IDOK lExitPage3 := .T. // More safe. Ensure we stop READing Gets before exit... //NTK_PostQuitMessage(0) // tell OS to terminate the application. Do not forget! //RETURN(.T.) // Quit RETURN( NTK_SendQuitEvent() ) // Same as both to previous lines : Terminate current app. ENDIF RETURN(.F.) // Do not quit, keep on current task ****** ****** ****** FUNCTION DOREPAINT(hWnd, message, nwParam, nlParam, hDC) //------ Old Style/fashion way to code ... more xBase-console like // Note that we can also use/mix Windows enhanced capabilities if // more power is needed... SET COLOR TO R+/W+ @ 050,050 SAY "Testing Easy TAB Controls..." ; INTO CONTEXT hDC RETURN(0) ****** ****** ****** FUNCTION DoPageManager( oTab ) LOCAL nPos LOCAL nPrevPageID := oTab:GetPreviousPage() LOCAL nCurPageID := oTab:GetActivePage() LOCAL hWndPrevPage := Nil LOCAL hWndCurPage := Nil // Retrieve the handle of the previous window container (if any) nPos := ASCAN( aPageInfo, {|Val| Val[PI_Id]==nPrevPageID } ) IF nPos > 0 hWndPrevPage := aPageInfo[nPos,PI_hWnd] // remember: aPageInfo[nPageID,hWndPage] ENDIF // Retrieve the handle of the current working window container (if any) nPos := ASCAN( aPageInfo, {|Val| Val[PI_Id]==nCurPageID } ) IF nPos > 0 hWndCurPage := aPageInfo[nPos,PI_hWnd] // remember: aPageInfo[nPageID,hWndPage] ENDIF IF nPrevPageID == ID_PAGE3 // Gets and READ are special controls so we're processing a special way, // by Creating and destroying each time the user enters or exits the page. CLEAR GETS OF hWndPrevPage // Clearing the current aGetList will automatically stop READing Gets lExitPage3 := .T. // Allow Exit from DO WHILE...ENDDO of Page3 once READ is over. ELSE // Otherwise, for other kind of controls, we just Hide the window container // of the previous page (if any) NTK_HideWindow( hWndPrevPage, .T. ) // Hide from screen ENDIF // Activate/show the window container of the current working page (if any) NTK_HideWindow( hWndCurPage, .F. ) // call back and show up to screen // Initialize the current page if not already existing // or reload needed informations... DO CASE CASE nCurPageID == ID_PAGE1 IF EMPTY(hWndCurPage) DoInitPage1(oTab) ELSE NTK_SetFocus(oB1:hWnd) // Some code here... ENDIF CASE nCurPageID == ID_PAGE2 IF EMPTY(hWndCurPage) DoInitPage2(oTab) ELSE // Reload Record (user might change Vars, meanwhile...) oB2:RefreshCurrent() NTK_SetFocus(oB2:hWnd) ENDIF CASE nCurPageID == ID_PAGE3 lExitPage3 := .F. // Disallow Exit from DO WHILE...ENDDO of Page3 meanwhile we're READing datas. DoInitPage3(oTab) ENDCASE RETURN(Nil) ****** ****** ****** FUNCTION DoInitPage1(oTab) LOCAL hWndTab := oTab:hWnd LOCAL nTop := 010 LOCAL nLeft := 010 LOCAL nBottom := __NTKMaxRow(hWndTab)-010 LOCAL nRight := __NTKMaxcol(hWndTab)-010 SELECT 1 @ nTop,nLeft TO nBottom,nRight CREATE BROWSE oB1 ; WITH DBAREA products; // This can also be used: WITH DBAREA 1; TITLES "PartNumber", "Description", "BarCode" ; FIELDS 1->Codeart, 1->Designart, 1->Codebarre, 1->PuaHT, 1->PuvHT; // Optional: Needed Field list... SIZES 100,200,110,90,90 ; INTO oTab:hwnd oB1:Escape := .F. // We don't want escape the browse when user applies on Esc key oB1:ForceColVisible := .F. // Force Tab to repaint oTab:Paint() // Store current page Informations in the devoted aPageInfo structure aPageInfo[1,PI_Id] := ID_PAGE1 aPageInfo[1,PI_hWnd] := oB1:hWnd RETURN(Nil) ****** ****** ****** FUNCTION DoInitPage2(oTab) LOCAL hWndTab := oTab:hWnd LOCAL nTop := 025 LOCAL nLeft := 025 LOCAL nBottom := __NTKMaxRow(hWndTab)-025 LOCAL nRight := __NTKMaxcol(hWndTab)-025 SELECT 2 @ nTop,nLeft TO nBottom,nRight CREATE BROWSE oB2 ; WITH DBAREA articles; // This can also be used: WITH DBAREA 2; TITLES "Sku", "BarCod", "Description"; FIELDS 2->CodArticle, 2->CodeBarre, 2->NomArticle, 2->PuHTachat, 2->PuHTvente ; // Optional: Needed Field list... SIZES 100,110,200,90,90 ; INTO hWndTab oB2:Escape := .F. // We don't want escape the browse when use applies on Esc key // Force Tab to repaint oTab:Paint() // Store current page Informations in the devoted aPageInfo structure aPageInfo[2,PI_Id] := ID_PAGE2 aPageInfo[2,PI_hWnd] := oB2:hWnd RETURN(Nil) ****** ****** ****** FUNCTION DoInitPage3(oTab) LOCAL hWndArtEdit LOCAL hBtnFont := NTK_GetStockObject(ANSI_VAR_FONT) LOCAL hGetFont := NTK_GetStockObject(ANSI_FIXED_FONT) LOCAL hGetBkgBrush := NTK_GetStockObject(WHITE_BRUSH) LOCAL hWndTab := oTab:hWnd LOCAL nTop := 010 LOCAL nLeft := 010 LOCAL nBottom := __NTKMaxRow(hWndTab)-020 LOCAL nRight := __NTKMaxcol(hWndTab)-020 PRIVATE vArtCode ,; vArtBarCode,; vArtName SELECT 2 // Articles vArtCode := 2->CODARTICLE vArtBarCode := 2->CODEBARRE vArtName := 2->NOMARTICLE CREATE WINDOW hWndArtEdit ; TITLE "Edit Articles..." ; // Note: Not visible in a child window. AT nLeft, nTop SIZE nRight, nBottom ; STYLE WS_CHILD+WS_VISIBLE+WS_BORDER ; INTO PARENT hWndTab ; ON PAINT DoRePaintPage3() ; ON EXIT DoExitPage3() ACTIVATE WINDOW hWndArtEdit NORMAL oTab:Paint() // Force Tab to repaint // Store current page Informations in the devoted aPageInfo structure aPageInfo[3,PI_Id] := ID_PAGE3 aPageInfo[3,PI_hWnd] := hWndArtEdit @ 130,__NTKMaxCol(hWndArtEdit)-120 PUSHBUTTON "Apply (F12)" SIZE 35,115 ; ID ID_BTN_APPLY ; TYPE NTK_BT_OWNERDRAWN ; STYLE BS_CENTER ; STATE NTK_BT_ENABLE ; SUPER ACCEL KEY K_F12 ; ACTION DoPage3Apply(hWndArtEdit, oTab) ; FONT hBtnFont ; OF hWndArtEdit ; MESSAGE "Save data Vars into their respective Database Fields..." @ 025,005 GET vArtCode ID ID_GET_1 ; PICTURE "@!" ; FONT hGetFont ; TEXTCOLOR NTK_RGB(0,0,128) ; BACKCOLOR TRANSPARENT ; STYLE GS_3DSUNKEN+GS_DISABLE; SIZE 20,120 ; MESSAGE "Enter the unique partnumber or SKU indentifying"+CR+; "the article..." @ 080,005 GET vArtBarCode ID ID_GET_2 ; PICTURE "@9" ; FONT hGetFont ; TEXTCOLOR NTK_RGB(0,0,128) ; BACKCOLOR TRANSPARENT ; BACKBRUSH hGetBkgBrush ; STYLE GS_3DSUNKEN ; SIZE 20,170 ; MESSAGE "Enter the BarCode corresponding"+CR+; "to the article..." @ 135,005 GET vArtName ID ID_GET_3 ; PICTURE "@!" ; FONT hGetFont ; TEXTCOLOR NTK_RGB(0,0,128) ; BACKCOLOR TRANSPARENT ; BACKBRUSH hGetBkgBrush ; STYLE GS_3DSUNKEN ; SIZE 20,260 ; MESSAGE "Enter the Name of the article..." // Here, READ is enclosed within a DO WHILE...ENDDO loop, because // We don't want the user to be able to quit the READ using tradional // ways: i.e. K_ESC, NTK_GET_GVK (F10), K_PGUP, K_PGDN // We only allow him to exit by switching to another page of // the current TabControl... For that reason, we're using lExitPage3 flag. //--- Invoke Get Reader System and auto process window's events for current page DO WHILE !(lExitPage3) READ INTO hWndArtEdit ; START FROM 2 ; FOCUS COLOR NTK_RGB(239,215,169); // Current (selected) Get color will be LT Brown BUTTON LIST aBtnList ; TOOLTIP **IF ( NTK_LastKey==NTK_GET_GVK .OR. NTK_LastKey()==K_PGUP .OR. NTK_LastKey()==K_PGDN ) ** // some code here (usually saving/replacing code) **ENDIF ENDDO CLEAR BUTTONS OF hWndArtEdit CLOSE WINDOW hWndArtEdit RETURN(Nil) ****** ****** ****** ****** ****** FUNCTION DoRepaintPage3(hWnd, message, nwParam, nlParam, hDC) LOCAL hSayFont := NTK_GetStockObject(ANSI_VAR_FONT) @ 005, __NtkMaxCol(hWnd)-135 SAY BITMAP ID BigDbEdit TRANSPARENCY BY NTK_RGB(255,000,255) INTO CONTEXT hDC SET COLOR TO N/T @ 010,005 SAY "1.Sku or PartNumber:" FONT hSayfont INTO CONTEXT hDC @ 065,005 SAY "2.BarCode:" FONT hSayfont INTO CONTEXT hDC @ 120,005 SAY "3.Description:" FONT hSayfont INTO CONTEXT hDC RETURN(0) ****** ****** ****** FUNCTION DoExitPage3(hWnd,Msg,wParam,lParam) RETURN(.T.) // .T. = Allow user to Quit - .F. = Do not quit, keep on current task ****** ****** ****** FUNCTION DoPage3Apply(hWndArtEdit, oTab) NTK_HourGlass(.T.) SELECT 2 // Articles IF !NtkNetRLock( "Cannot save datas. Someone else is already using this record - "+CR+; "Do you want to retry?", 5, 2 ) // 5=number of times to retry. 2=DB alias // some code or msgbox here... ELSE REPLACE 2->CODARTICLE WITH vArtCode REPLACE 2->CODEBARRE WITH vArtBarCode REPLACE 2->NOMARTICLE WITH vArtName ENDIF NTK_HourGlass(.F.) RETURN .T. ****** ****** ******