NTK and The NTK Project
are properties of Jn Dechereux
Home | Documentation | FAQ.

Vanilla 1.1.8 is a product of Lussumo. More Information: Documentation, Community Support.

Welcome Guest!
Want to take part in these discussions? If you have an account, sign in now.
If you don't have an account, apply for one now.
    •  
      CommentAuthorohaldi
    • CommentTimeFeb 28th 2017
     
    Hello,
    How can I create a message bar (Status bar with section) at the bottom of main windows?

    Regards
    Otto
    •  
      CommentAuthorxbasefan
    • CommentTimeFeb 28th 2017 edited
     
    CreateStatusWindow() should do the job.
    http://msdn.microsoft.com/en-us/library/bb760762%28v=VS.85%29.aspx
    wilson

    e.g.
    . . .
    #include "ntkdll.ch"
    
    Static hStatusBar
    
    Func Main()
    . . .
    CREATE WINDOW hWnd TITLE ...
    . . .
    
    ACTIVATE WINDOW hWnd NORMAL
    
    hStatusBar := CreateStatusWindow( WS_CHILD+WS_VISIBLE, "Your status bar message.", hWnd, WM_USER+100 )
    
    AUTO HANDLE EVENTS OF WINDOW hWnd
    . . .
    
    CLOSE WINDOW hWnd
    Return(Nil)
    
    
    /* change statusbar message   */
    Func SetStatusBarMsg(hWndSB, cNewMsg)
    Return( NTK_SetWindowText(hWndSB, cNewMsg) )
    
    
    /* wrapper for external C/Win32 API */
    _DLL FUNCTION CreateStatusWindow( style as long, lpsztext as lpctstr, hwndParent as handle, wID as uint );
                                      AS HWND PASCAL:Comctl32.CreateStatusWindowA
    
    
    •  
      CommentAuthorohaldi
    • CommentTimeFeb 28th 2017
     
    Many thanks for your help
    Work, but it write the message in titel aera, not in StatusBar!
    With GTWVW I have had the possibility to make more area. Can I do this with NTK?
    See picture
    •  
      CommentAuthorxbasefan
    • CommentTimeMar 1st 2017
     
    > Work, but it write the message in titel aera, not in StatusBar!
    hmmm, you must have used the wrong handle.
    the right syntax is:
    SetStatusBarMsg( hStatusBar, "the new message...")


    >With GTWVW I have had the possibility to make more area. Can I do this with NTK?
    easy, just call NTK_SendMessage() with the apropriated statusbar messages.
    all the needed documentation is available here:
    https://msdn.microsoft.com/en-us/library/windows/desktop/ff486035%28v=vs.85%29.aspx

    and this snippet should get you started:
    . . .
    ACTIVATE WINDOW hWnd NORMAL  
     
    
    //hStatusBar := CreateStatusWindow( WS_CHILD+WS_VISIBLE+SBT_TOOLTIPS, nil, hWnd, WM_USER+100 )
    
    // Same as previous, but more Win32/64
    hStatusBar := NTK_CreateWindowEx(0,;
                                     STATUSCLASSNAME,;
                                     NIL,;
                                     WS_CHILD+WS_VISIBLE+SBT_TOOLTIPS+SBARS_SIZEGRIP,;
                                     0,;
                                     0,;
                                     0,;
                                     0,;
                                     hWnd, WM_USER+100 )
    
    
    // Change default height, if needeed.
    NTK_SendMessage(hStatusBar, SB_SETMINHEIGHT, 50, 0)  // e.g. 50 pixel height
    NTK_SendMessage(hStatusBar, WM_SIZE, 0 , 0 )
    
    /* Define the background color */
    //NTK_SendMessage(hStatusBar, SB_SETBKCOLOR, 0, NTK_RGB(0,0,255) )  // Blue
    
    /* Create 4 panels */
    paSBWidthParts := __NTKA2BIN( {110,200,800,-1} , "int,int,int,int")  // Size of each pane in pixel
    /* paSBWidthParts := L2BIN(100)+L2BIN(200)+L2BIN(800)+L2BIN(-1) // same as previous  */
    NTK_SendMessage(hStatusBar, SB_SETPARTS, 4, @paSBWidthParts )
    
    /* Set Pane 1 */
    NTK_SendMessage(hStatusBar, SB_SETTEXT, 0, "Status Part 0...")
    NTK_SendMessage(hStatusBar, SB_SETTIPTEXT, 0, "Help on part 0")
    hIcon  := NTK_LoadIcon(nil,  IDI_EXCLAMATION) // Windows stockobject
    NTK_SendMessage(hStatusBar, SB_SETICON, 0, hIcon )
    
    /* Set Pane 2 */
    //NTK_SendMessage(hStatusBar, SB_SETTEXT, 1, "Status Part 1" )
    NTK_SendMessage(hStatusBar, SB_SETTIPTEXT, 1, "Help on part 1")
    hIcon  := NTK_LoadIcon(nil,  IDI_ASTERISK) // Windows stockobject
    NTK_SendMessage(hStatusBar, SB_SETICON, 1, hIcon )
    
    /* Set Pane 3 */
    NTK_SendMessage(hStatusBar, SB_SETTEXT, 2, "Status Part 2")
    hIcon  := NTK_LoadIcon(nil,  IDI_HAND) // Windows stockobject
    NTK_SendMessage(hStatusBar, SB_SETICON, 2, hIcon )
    
    /* Set Pane 4 */
    NTK_SendMessage(hStatusBar, SB_SETTEXT, 3, Time())
    
    /* Ensure our statusbar is correctly displayed */
    NTK_ShowWindow(hStatusBar, SW_SHOW)
    
    
    
    AUTO HANDLE EVENTS OF WINDOW hWnd 
    . . .
    
    


    hth.
    wilson
    •  
      CommentAuthorohaldi
    • CommentTimeMar 5th 2017
     
    Many thanks work well.
    •  
      CommentAuthorohaldi
    • CommentTimeMar 6th 2017
     
    Small question:
    With this example it is possible to have the text in red?
    Or do I have to use your sample above?

    /* change statusbar message */
    Func SetStatusBarMsg(hWndSB, cNewMsg)
    Return( NTK_SetWindowText(hWndSB, cNewMsg) )

    /* wrapper for external C/Win32 API */
    _DLL FUNCTION CreateStatusWindow( style as long, lpsztext as lpctstr, hwndParent as handle, wID as uint );
    AS HWND PASCAL:Comctl32.CreateStatusWindowA
    •  
      CommentAuthorxbasefan
    • CommentTimeMar 7th 2017
     
    not easy as MS does not give us any 'SB_SETTEXTCOLOR' msg to do this.
    (as often they have a tendency not to complete what they started)

    the only way they propose to achieve this is to change the the statusbar pan style to make it owner-drawn and then intercept the WM_DRAWITEM message in the parent window. quite a bit complex but doable.
    imo, you'll need to:
    1. create an array that contains pane informations. ie. paneid, text, fgcolor, bgcolor;
    2. inform Windows when you are defining a pane of the statusbar that needs to be an owner-drawn part;
    3. write your own function to display colored text within the specified pane rect;
    4. define & attach an event handler to your parent window that calls your function when a WM_DRAWITEM occurs.

    hth
    wilson
    •  
      CommentAuthorxbasefan
    • CommentTimeMar 7th 2017 edited
     
    example based on portions of my own code - so feel free to remove unwanted.
    ...
    Static hStatusBar
    Static aSB_PaneColor := { {0, "", NTK_RGB(255,0,0),   TRANSPARENT } ,; // Pane #1: Red   / Transparent
                              {1, "", NTK_RGB(0,255,0),   TRANSPARENT } ,; // Pane #2: Green / Transparent
                              {2, "", NTK_RGB(0,0,255),   TRANSPARENT } ,; // Pane #3: Blue  / Transparent
                              {3, "Colored text!", NTK_RGB(0,128,128), TRANSPARENT } ,; // Pane #4: DKCyan / Transparent
                            }
    
    
    FUNCTION MAIN()
    . . .
    
    CREATE WINDOW hWnd ;
    TITLE "my window with a statusbar" ;
    STYLE WS_OVERLAPPEDWINDOW;
    ON MSG DoEventHandler();
    ON PAINT DoRePaint()
    
    . . .
    
    
    hStatusBar := NTK_CreateWindowEx(0,;
                                     STATUSCLASSNAME,;
                                     NIL,;
                                     WS_CHILD+WS_VISIBLE+SBT_TOOLTIPS+SBARS_SIZEGRIP,;
                                     0,;
                                     0,;
                                     0,;
                                     0,;
                                     hWnd, WM_USER+100 )
    
    // Change default height
    NTK_SendMessage(hStatusBar, SB_SETMINHEIGHT, 50, 0)  // e.g. 50 pixel height
    NTK_SendMessage(hStatusBar, WM_SIZE, 0 , 0 )
    
    . . .
    
    /* Set Pane 3 */
    NTK_SendMessage(hStatusBar, SB_SETTEXT, 2, "Status Part 2")
    hIcon  := NTK_LoadIcon(nil,  IDI_HAND) // Windows stockobject
    NTK_SendMessage(hStatusBar, SB_SETICON, 2, hIcon )
    
    /* Set Pane 4 */
    /* NTK_SendMessage(hStatusBar, SB_SETTEXT, 3, Time()) */
    
    // change statusbar style to make it Owner-drawn
       // according to MSDN documentation you might be tempted to write:
       // NTK_SendMessage(hStatusBar, SB_SETTEXT, NTK_MakeWParam( NTK_MakeWord(3,SBT_OWNERDRAW), NULL),  Time()) )
       // this will not work. by appearances, the SBT_ styles are defined so that they will automatically appear
       // in the high byte of the low word if you just OR them with your index value.
       // MS doc is sometimes a real nightmare!
    // this one works properly:
    NTK_SendMessage( hStatusBar, SB_SETTEXT, SBT_OWNERDRAW+3, Nil )
    
    
    /* Ensure our statusbar is correctly displayed */
    NTK_ShowWindow(hStatusBar, SW_SHOW)
    
    . . .
    
    CLOSE WINDOW hWnd
    Return(nil) // end of main
    
    
    Function DoEventHandler(hWnd, nMsg, nWParam, nLParam)
    
    IF nMsg == WM_DRAWITEM
       // according to MS documentation, the nlParam contains the lpDrawItemStruct
       If SB_SetPaneColor( nlParam,  aSB_PaneColor )
          // according to MS documentation, TRUE means we processed the message
          Return(1)
       Endif
    
    ELSEIF nMsg==WM_SIZE   // parent window size has changed
        //nSizeType := nWParam            // resizing flag: SIZE_MAXIMIZED, SIZE_*
        //nWidth := NTK_LoWord(nLParam)   // width of parent client area
        //nHeight := NTK_HiWord(nLParam)  // height of parent client area
    
        // auto-adjust our statusbar to the parent new size
        NTK_MoveWindow( hStatusBar, nil,nil,nil,nil, .T. )
        Return(0) // zero means we processed the message
    
    ENDIF
    
    Return( NTK_DefWindowProc(hWnd, nMsg, nWParam, nLParam) )
    
    
    Function SB_SetPaneColor( lpDrawItemStruct, aPaneColor )
    Local aDrawItemStruct := NTK_DRAWITEM2A(lpDrawItemStruct)  // see DRAWITEM/DIS structure members in NTKGDI.CH
    Local hStatBar := aDrawItemStruct[DIS_hwndItem]   // the handle to our statusbar
    Local nPaneID  := aDrawItemStruct[DIS_itemID]     // the pane index in which the OS is ready to draw
    Local hDC      := aDrawItemStruct[DIS_hDC]        // a valid DC to the window statusbar
    Local nLeft    := aDrawItemStruct[DIS_rcLeft]     //     // x offset  --
    Local nTop     := aDrawItemStruct[DIS_rcTop]             // y offset    | the pane rectangle
    Local nRight   := aDrawItemStruct[DIS_rcRight] - nLeft   // width       | coordinates
    Local nBottom  := aDrawItemStruct[DIS_rcBottom] - nTop   // height    --
    Local nPos
    
       // retrieve color information about pane being drawn
       nPos := ASCAN( aPaneColor, { |x| x[1]==nPaneID .AND. !EMPTY(x[2]) } )
    
       IF nPos>0
          // draw text in the pane
          @ nTop+2, nLeft+2 SAY aPaneColor[nPos, 2] SIZE nBottom-2, nRight-2 ;
                                STYLE DT_CENTER+DT_VCENTER+DT_SINGLELINE ;
                                FONT NTK_GetStockObject(ANSI_VAR_FONT) ;
                                TEXTCOLOR aPaneColor[nPos, 3] ;
                                BACKCOLOR aPaneColor[nPos, 4] ;
                                INTO CONTEXT hDC
       ELSE
          // no specific color information found for this nPaneID
          // so do nothing. ie. standard behaviour
          RETURN(.F.)
       ENDIF
    
    Return(.T.)
    
    
    •  
      CommentAuthorohaldi
    • CommentTimeMar 8th 2017
     
    Hello
    Once again many thanks for the great information.
    As expected, with NTK you have to write a lot of code to resolve something very simple!
    Regards
    Otto
    •  
      CommentAuthorLucas
    • CommentTimeMar 8th 2017 edited
     
    Hi there.

    Wilson: Great article, my vote is 5. Many thanks for the guidance.
    Once again your article demonstrates how much the fact of using MS controls make us dependent
    of their visual style and above all of their 'crappy' way to always complexify what is simple.

    Otto: Wilson didn't show you the NTK way, but the Windows Owner-Drawn way. i.e. understand: the official MS way
    of doing something basic they've forgotten (or didn't take time) to implement properly. Have a look here:
    https://msdn.microsoft.com/en-us/library/windows/desktop/bb760758%28v=vs.85%29.aspx
    IMO, this a great chance for us to have NTK that allows us to access such facilities usually reserved to low level languages.

    However, I agree with you: 'lot of code to resolve something simple'. BTW, just curious - how did you that do that with GTWVW?
    did you have access to whole Win32 API at this granularity level?

    Personnaly, I have solved this issue long time ago in a very simple manner:
    Just a bitmap and couple of @BOX and @SAY commands in the paint proc!
    advantages:
    easy to write
    easy to maintain
    auto-resize. No need of WM_SIZE/NTK_MoveWindow/NTK_SetWindowPos()

    FYI: it is even possible to get something with a fancy look if you replace the @BOX with a @SAY..WALLPAPER...

    BR,
    Lucas

    #include "windows.ch"
    #include "ntkacc.ch"
    #include "ntkcmd.ch"
    #include "ntkcmdex.ch"
    #include "wNtk.ch"
    #include "wNtkKeys.ch"
    
    
    FUNCTION MAIN()
    LOCAL hWndMain
    LOCAL cWinTitle := "Basic Header & Status bars"
    
    CREATE WINDOW hWndMain;
           TITLE cWinTitle;
           STYLE WS_OVERLAPPEDWINDOW;
           AT 0,0 SIZE CW_USEDEFAULT, CW_USEDEFAULT;
           ON PAINT DoMainRePaint()
    
    
    ACTIVATE WINDOW hWndMain CENTER
    AUTO HANDLE EVENTS OF WINDOW hWndMain
    
    CLOSE WINDOW hWndMain
    RETURN
    
    ////////////////////////////////////////////////////////////////////////////
    FUNCTION DoMainRepaint(hWnd, message, nwParam, nlParam, hDC)
    Local nMaxRow := __NtkMaxRow(hWnd)
    Local nMaxCol := __NtkMaxCol(hWnd)
    Local hBmpResize := NTK_LoadBitmap(NULL, OBM_SIZE) 
    Local hIconAlert := NTK_LoadIcon(NULL, IDI_EXCLAMATION)
    Local nHHB := 45  // Header bar height
    Local nHSB := 35  // Status bar height
    
    
    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Draw the Header Bar
    ////////////////////////////////////////////////////////////////////////////////////////////////
    SET RGB COLOR TEXT NTK_RGB(255,128,0) BACK NTK_RGB(100,100,100)  
    @ 0,0 SAY ">>> Header bar Title <<<" SIZE nHHB, nMaxCol;
              STYLE DT_SINGLELINE+DT_CENTER+DT_VCENTER;
              FONT NTK_GetStockObject(SYSTEM_FONT);
              INTO CONTEXT hDC
    ////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    
    //
    // Some code here...
    //
    
    
    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Draw a pseudo 3D raised Status Bar
    ////////////////////////////////////////////////////////////////////////////////////////////////
    @ nMaxRow-nHSB,1 , nMaxrow,nMaxCol BOX NTK_BXS_3DRAISED INTO CONTEXT hDC COLOR "N+/N+"
    
    // SB Part one
    SET COLOR TO N/T
    @ nMaxRow-nHSB,4 SAY ICON HANDLE hIconAlert INTO CONTEXT hDC
    @ nMaxRow-(nHSB-2),2 SAY "Part 1 - some text...";
                       SIZE (nHSB-2),200  FONT NTK_GetStockObject(ANSI_VAR_FONT);
                       STYLE DT_SINGLELINE+DT_CENTER+DT_VCENTER;
                       INTO CONTEXT hDC
    
    // SB Part two
    @ nMaxRow-(nHSB-2),200, nMaxrow-2,202 BOX NTK_BXS_3DRAISED INTO CONTEXT hDC COLOR "N+/N+"
    SET COLOR TO B/T
    @ nMaxRow-(nHSB-2),210 SAY "Part 2 - blah, blah, blah, blah";
                       SIZE (nHSB-2),200  FONT NTK_GetStockObject(ANSI_VAR_FONT);
                       STYLE DT_SINGLELINE+DT_CENTER+DT_VCENTER;
                       INTO CONTEXT hDC
    
    
    // SB Part three
    @ nMaxRow-(nHSB-2),nMaxCol-97, nMaxrow-2,nMaxCol-95 BOX NTK_BXS_3DRAISED INTO CONTEXT hDC COLOR "N+/N+"
    SET COLOR TO R+/T
    @ nMaxRow-(nHSB-2),nMaxCol-100 SAY Time();
                       SIZE (nHSB-2),100  FONT NTK_GetStockObject(SYSTEM_FONT);
                       STYLE DT_SINGLELINE+DT_CENTER+DT_VCENTER;
                       INTO CONTEXT hDC
    
    
    @ nMaxRow-20,nMaxCol-20 SAY BITMAP HANDLE hBmpResize;
                                TRANSPARENCY BY NTK_RGB(240,240,240);
                                INTO CONTEXT hDC
    
    NTK_DeleteObject(hIconAlert)
    NTK_DeleteObject(hBmpResize)
    ////////////////////////////////////////////////////////////////////////////////////////////////
    RETURN(0)
    
    
    •  
      CommentAuthorohaldi
    • CommentTimeMar 8th 2017 edited
     
    &gt;BTW, just curious - how did you that do that with GTWVW?
    See sample below!

    &gt;did you have access to whole Win32 API at this granularity level?
    In fact, I'm not a guru in low level programming. I used GTWVW principally for the Windows function.

    Small sample code for the status bar
    WVW_SBCreate() // Create status bar for current window, with one part.
    WVW_SBAddPart(,,60) // Add part 1
    WVW_SBAddPart(,,100) // Add part 2 etc.
    // to write a message in part 1
    WVW_SBSetText(0,0,&quot;Message in red&quot;, StrZero( RGB( 255,0,0 ), 8 ), StrZero( RGB( 0,0,0 ), 8 ) )
    // That's all. More info at: https://harbour.github.io/doc/gtwvw.html

    Your sample is very helpful. Thanks.
    •  
      CommentAuthorxbasefan
    • CommentTimeMar 9th 2017
     
    these are nothing else but wrappers to SB_* messages i explained in the above. now you know how that really works in the background it should not take you long time to write similar functions. btw, would be great if you'd share this with the community in return. sure this kind of topic would be helpful to other newbies...
    wilson
    •  
      CommentAuthorxbasefan
    • CommentTimeMar 9th 2017
     
    hi Lucas:
    thanks. i appreciate you appreciate. :wink:
    wilson
    •  
      CommentAuthorohaldi
    • CommentTimeMar 10th 2017
     
    I still have problem to understand NTK logic!
    Your Sample above work well. I like to activate the MsgBar once this is OK with DoRepaint().
    Now I like to have my own function to change the message in part one only or to update the time?

    I tried many way ma last idea was this function! but do not work. I got a small black rectange some ware on the screen!

    FUNCTION BarMsg(hWnd, nMsg, nWParam, nLParam, hDC)
    Local nMaxRow := __NtkMaxRow(hWnd)
    Local nMaxCol := __NtkMaxCol(hWnd)
    Local hBmpResize := NTK_LoadBitmap(NULL, OBM_SIZE)
    Local hIconAlert := NTK_LoadIcon(NULL, IDI_EXCLAMATION)
    Local nHHB := 45 // Header bar height
    Local nHSB := 35 // Status bar height

    // SB Part one
    SET COLOR TO N/T
    @ nMaxRow-nHSB,4 SAY ICON HANDLE hIconAlert INTO CONTEXT hDC
    @ nMaxRow-(nHSB-2),2 SAY nMsg;
    SIZE (nHSB-2),200 FONT NTK_GetStockObject(ANSI_VAR_FONT);
    STYLE DT_SINGLELINE+DT_CENTER+DT_VCENTER;
    INTO CONTEXT hDC
    Return(nil)
    •  
      CommentAuthorLucas
    • CommentTimeMar 10th 2017 edited
     
    Otto:
    This not a particular logic due to NTK but to the Windows GDI concept itself. Have a closer look at this:
    https://msdn.microsoft.com/fr-fr/library/windows/desktop/ff381401%28v=vs.85%29.aspx

    BTW, you need to understand that under MS-Windows all is window. ie. your main window, a scrollbar, a button, a edit/get, etc.
    ...and each window has its own callback wndproc that receives different kind of messages/events (WM_*) which have to be processed or ignored, depending on what the developer wants to do.

    Having said that, let's talk about the WM_PAINT message and the GDI concept.

    1. The OS send a WM_PAINT to the window wndproc in 3 cases:
    1.1. At the window startup, just after the WM_CREATE message has been treated (or not).
    1.2. Each time the developer decides to invalidate/refresh the whole window client area or a portion of this client area. To do so, he can use the Win32 API: NTK_InvalidateRect(hWnd, aRect, lEraseBkg).
    1.3. When the GDI decides the client area or portion of it needs to be refreshed consequently to actions of other application/s (e.g. overlapping).

    2. Processing the WM_PAINT and opening/closing a Device Context.
    2.1. When the developer intercepts the WM_PAINT message and prior to implement some drawings, he must ask the MS-Windows GDI for a valid Device Context.
    2.2 To do so, he has to intialize a PAINTSTRUCTure (aPS) and pass it to the BeginPaint().
    2.3 Then, he can draw inside the returned hDC...
    2.4 Afterward, once paintings operations are completed, just close the DC and
    return 0 to inform OS that the WM_PAINT has been succesfully processed.
    FUNCTION MYWNDPROC( hWnd, nMessage, nwParam, nlParam)
    Local aPS := ARRAY(PS_LENGTH) // see NTKGDI.CH
    Local hDC
    Local aRect
    
    DO CASE
       CASE message == WM_CREATE
    		  // Do some code here
            RETURN(0) // Inform MS-Windows we've processed the message.
    
       CASE message == WM_PAINT
            hDC := NTK_BEGINPAINT( hWnd, aPS )
            aRect := NTK_GetClientRect(hWnd)
                NTK_TextOut( hDC, 10, 10 Hello: Time is "+Time() )
            NTK_ENDPAINT( hWnd, aPS )
            RETURN(0)
    
       CASE message == WM_DESTROY
            NTK_PostQuitMessage(0)
            RETURN(0)
    ENDCASE
    
    // Default processing of all the other messages...
    RETURN( NTK_DefWindowProc(hWnd, nMessage, nwParam, nlParam) )
    

    END OF PART 1 OF 2
    •  
      CommentAuthorLucas
    • CommentTimeMar 10th 2017 edited
     
    PART 2 OF 2:

    *** FORTUNATELY ***, with NTKRad all the above stuff is fully hidden. NTKRad main mission is to handle the burden for us.
    However, developer still has the ability to declare/connect 4 procedures to the CREATE WINDOW... instruction. i.e.
    CREATE WINDOW hWndMain TITLE 'My Main' STYLE WS_OVERLAPPEDWINDOW;
           ON INIT  DoInitProc();  // Response to the WM_CREATE message
           ON PAINT DoPaintProc(); // Response to the WM_PAINT message
           ON MSG   DoWndProc();   // User Defined proc for processing other WM_* messages
           ON EXIT  DoExitProc()   // Response to the WM_DESTROY message
    

    Each of those 4 procedures is optional.
    But when mentionned, it causes NTKRad to automatically execute the specified procedure with the right parameters when the internal wndproc receives the concerned message. find out more in NTKRad manual.

    So, if we consider this basic Prg:
    . . .
    FUNCTION MAIN()
    . . .
    CREATE WINDOW hWndMain TITLE 'My Main'
           STYLE WS_OVERLAPPEDWINDOW;
           ON PAINT DoPaintProc()
    
    ACTIVATE WINDOW hWndMain NORMAL
    
    AUTO HANDLE EVENTS OF WINDOW hWndMain
    
    
    CLOSE WINDOW hWndMain
    RETURN // End of main.
    
    Procedure DoPaintProc(hWnd, nMsg, nWParam, nLParam, hDC)
    
    SET COLOR TO R+/W
    @ 10,50 SAY Hello: Time is "+Time() SIZE 30,200 INTO CONTEXT hDC
    
    RETURN(0)
    

    We can notice that NTKRad avoids us the hassle of writting a wndproc, process the WM_PAINT and get a valid DC as explained in the above, and so on.
    Instead of that, the specified DoPaintProc() is automaticatically performed with a valid hDC.
    The only thing we have to do is to mention this hDC in our drawing instructions.
    e.g. @ y,x SAY "blah, blah" INTO CONTEXT hDC.
    And we even don't have to release it!

    Now, each time we need to update/refresh our window or just a specific portion, we simply have to call, from any parts of our PRG, one of the NTK refreshing instructions. i.e.
    NTK_InvalidateRect(hWndMain) // Refresh the whole window
    // Only refresh the Time() area
    NTK_InvalidateRect(hWndMain, {50,10,200,30}, .T.)
    NtkRePaint(hWnd, 10,50,40,250)
    NtkRePaint(hWnd, 10,50,40,250, .T.)  // less flicking
    REFRESH SCREEN OF hWndMain FROM 10,50 TO 30,200
    

    Nothing more... NTK automatically performs the DoPaintProc() when needed and Window GDI does the rest.
    No need to write additional code nor to take care about which portion must be repainted in case another application is dragged over ours, no need to savescreen/restorescreen, etc.
    IMO, very few lines of code compared to all the complex stuff done by the GDI in background!


    *** N.B. ***
    If you can't (or don't want to) use the std GDI technic, NTKRad also allows you to refresh specific data with any @...output commands everywhere in your PRG. Exactly as you used to do it with Clipper.
    Though, you'll have to specify the concerned window instead of the hDC.
    Indeed, unlike a DOS program, a Windows application may handle several windows at same time which have possibility to overlap each others. e.g.
    @ 10,10 SAY Hello: Time is "+Time() SIZE 30,200 INTO WINDOW hWndMain
    

    Please, note that this technic is a bit slower cause NTKRad has to maintain specific informations into an aSayList array to avoid your text, box, bitmap, etc. being partially erased when an other application overlaps yours. AFAIK, it's up to the developer to initialize/clear the aSayList.

    It took me a buch of time to write this. So really hope it helps.

    BR,
    Lucas

    P.S.
    Forum: feel free to correct me if i'm wrong or to amend what would seem incomplet to you.
    And apologises in advance for typos and spelling mistakes.


    END OF PART 2 OF 2
    •  
      CommentAuthorLucas
    • CommentTimeMar 10th 2017 edited
     
    >Your Sample above work well. I like to activate the MsgBar once this is OK with DoRepaint().
    >Now I like to have my own function to change the message in part one only or to update the time?
    >
    >I tried many way ma last idea was this function! but do not work. I got a small black rectange some ware >on the screen!
    >
    >FUNCTION BarMsg(hWnd, nMsg, nWParam, nLParam, hDC)
    >Local nMaxRow := __NtkMaxRow(hWnd)
    >Local nMaxCol := __NtkMaxCol(hWnd)
    >Local hBmpResize := NTK_LoadBitmap(NULL, OBM_SIZE)
    >Local hIconAlert := NTK_LoadIcon(NULL, IDI_EXCLAMATION)
    >Local nHHB := 45 // Header bar height
    >Local nHSB := 35 // Status bar height
    >
    >// SB Part one
    >SET COLOR TO N/T
    >@ nMaxRow-nHSB,4 SAY ICON HANDLE hIconAlert INTO CONTEXT hDC
    >@ nMaxRow-(nHSB-2),2 SAY nMsg;
    >SIZE (nHSB-2),200 FONT NTK_GetStockObject(ANSI_VAR_FONT);
    >STYLE DT_SINGLELINE+DT_CENTER+DT_VCENTER;
    >INTO CONTEXT hDC
    >Return(nil)


    Your snippet works well here. As mentioned in the above, you only have to update the time area with NTK_InvalidateRect() or NtkRepaint().

    To help you figure out, feel free to rebuild and give a try to the attached sample.

    BR,
    Lucas
    •  
      CommentAuthorohaldi
    • CommentTimeMar 11th 2017
     
    Hello Lucas,

    >It took me a buch of time to write this. So really hope it helps.
    Many thanks for the time you used for me.
    I see NTK is more complex as I thought! I have a good experience with clipper/xharbour, but here it’s a little more complex!
    You included sample helped me a lot.
    I will try to put all you information in my first exercise. I send it to you next week.
    Small question are you form the NTK Team?
    Regards
    Otto
    •  
      CommentAuthorLucas
    • CommentTimeMar 14th 2017
     
    Hi Otto:
    >You included sample helped me a lot.
    Glad to see this contribution points you the right direction. Also hope it will be useful to others.

    >I will try to put all you information in my first exercise. I send it to you next week.
    Well, not sure to have enough time for that. If you read the msdn link in my previous post, you
    should be able to figure out how works Windows GDI and solve your issue on your own.

    >Small question are you form the NTK Team?
    Many thanks for the comparaison but no.

    BR,
    Lucas
    •  
      CommentAuthorohaldi
    • CommentTimeMar 17th 2017 edited
     
    Hello Lucas,

    Here my example. Hope another NTK user can get any information.

    Regards
    Otto
    •  
      CommentAuthorLucas
    • CommentTimeMar 20th 2017
     
    Hello Otto:
    Well, you are flying now!
    Great example, thanks for sharing this. :thumbup:
    I'm sure it's gonna help someone sooner or later.
    BR,
    Lucas