******************************************************************************** * Program : BMROTATE.PRG * Launch BMROTATE.EXE * Aim : Show how to program Applications using Windows traditional manner, * ..........: with NTKCORE GUI (low level) set of functions for X/HARBOUR. * ..........: This sample illustrate GDI drawing possibilities of NTKCORE : * ..........: Memory Bitmap creation, Bitmap Screen Shoot & grabbing and Bitmap Rotation... * Make......: Juste type MK BMROTATE * Date : 17/05/06 * Author(s) : Jn DECHEREUX * Copyright : (c) 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... ******************************************************************************** * * For further explanations about GDI drawing purpose, feel free to consult MSDN * documentation website at : * http://msdn.microsoft.com/library/default.asp * * As, explanations about the advanced drawing techniques used in this sample are * beyond the scope of NTKCORE's manual, do not hesitate to dive in Petzold's book... * ********************************************************************************** // Harbour includes #include "cstruct.ch" // NTK includes #include "wintypes.ch" #include "windows.ch" #include "ntkgdi.ch" #include "ntkmsg.ch" #include "ntkacc.ch" #include "ntkcctrl.ch" #include "ntkttips.ch" #include "wNtk.ch" #define CR CHR(13) #define CRLF CHR(13)+CHR(10) #define TAB CHR(9) STATIC hTimer 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 := "Example of BMROTATE control with NTKCore for X/HRB !" LOCAL hWndDemo PRIVATE aDemoFont1 PRIVATE hDemoFont1 PRIVATE hTuxBmp := NTK_ReadPictureToBmp( "Tux.bmp" ) PRIVATE nBmpAngle := 0.2 // The current Rotation angle // ----- 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, BMROTATEs... NTK_InitCommonControlsEx( ICC_DATE_CLASSES + ICC_BAR_CLASSES + ICC_STANDARD_CLASSES + ICC_WIN95_CLASSES ) IF !NTK_RegisterClassEx( CS_HREDRAW + CS_VREDRAW,; // CS_OWNDC + CS_VREDRAW + CS_HREDRAW + CS_DBLCLKS,; hInst,; hIcon,; hCurs,; hBrush,; "NTKFEN",; { |hWnd, message, nwParam, nlParam|; MAINWNDPROC(hWnd, message, nwParam, nlParam) } ) NTK_MsgBox( , "Can't register NTKFEN class..." ) RETURN Nil ENDIF hWndDemo = NTK_CreateWindowEx( WS_EX_WINDOWEDGE, "NTKFEN", cWinTitle, ; F_MAX+ WS_OVERLAPPED + WS_CAPTION + WS_THICKFRAME +WS_SYSMENU,; 0, 0, CW_USEDEFAULT, CW_USEDEFAULT ) IF hWndDemo == 0 NTK_MsgBox( , "Can not create MAIN Window..." ) RETURN Nil ENDIF aDemoFont1 := { -48,12,0,0,700, .F., .F., .F., 1, 0, 0, 0, 0, "ARIAL" } hDemoFont1 := NTK_CreateFont( aDemoFont1 ) IF hDemoFont1 == 0 NTK_MsgBox( , "Can not create DemoFont1..." ) RETURN Nil ENDIF NTK_ShowWindow( hWndDemo, SW_NORMAL ) NTK_UpdateWindow( hWndDemo ) // ---------------------------------- NTK's Main Events (Windows Msg) Loop DO WHILE NTK_GetMessage( NTK_aMSG, 0 ) //,hWndDemo,0,0 ) NTK_TranslateMessage( NTK_aMSG ) NTK_DispatchMessage( NTK_aMSG ) ENDDO NTK_DeleteObject( hDemoFont1 ) NTK_DeleteObject( hTuxBmp ) NTK_SelectWindow( hWndDemo ) NTK_DestroyWindow( hWndDemo ) NTK_UnregisterClass( "NTKFEN", hInst ) RETURN ****** ****** ****** FUNCTION MAINWNDPROC( hWnd, message, nwParam, nlParam) LOCAL nI LOCAL aPS := { 0,.T.,0,0,0,0,.T.,.T.,nil } // 9 elements, see NTKGDI.CH LOCAL hDC := 0 LOCAL nRed := NTK_RGB(255,0,0) LOCAL nBlue := NTK_RGB(0,0,128) DO CASE CASE message == WM_CREATE // Initialize a Timer to 100 ms delay between screen updates hTimer := NTK_SetTimer(hWnd, 1, 100 ) // Create multiline tooltip info bubble covering the whole window // Syntaxe NTK_CreateMLToolTip(nStyle,cTTMsg,nLeft,nTop,nRight,nBottom,hWndP,nuFlags,nuId,hInst ) -> hWndTT NTK_CreateMLToolTip( WS_POPUP + TTS_NOPREFIX + TTS_BALLOON,; "Hey my litte boy!"+CR+; "Move the mouse cursor over Tux..."+CR+; "or just try to overlap Tux's area dragging "+CR+" another window on over...",; 0,0, CW_USEDEFAULT, 230,; hWnd,; TTF_SUBCLASS) CASE message == WM_TIMER // Handle the redraw with the timer nBmpAngle = nBmpAngle + .05 // NTK_InvalidateRect(hWnd) NTK_RedrawWindow( hWnd, Nil, nil, RDW_INVALIDATE+RDW_UPDATENOW ) // Less flicking RETURN(0) CASE message == WM_CHAR IF nwParam==27 // K_ESC IF NTK_MsgBox( hWnd,; "Do you really want to quit ?",; "Your Attention Please !",; MB_OKCANCEL+MB_ICONQUESTION ) == IDOK NTK_PostQuitMessage(0) ENDIF ENDIF RETURN(0) CASE message == WM_RBUTTONDOWN 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_PAINT hDC := NTK_BEGINPAINT( hWnd, aPS ) DoDrawRotationBmp( hWnd, hDC ) NTK_TextOut( hDC, 100, 400, "Press Esc or Alt-F4 to quit..." ) hOldObj := NTK_SelectObject( hDC, hDemoFont1 ) NTK_SetTextColor( hDC, nRed ) NTK_SetBkMode( hDC, TRANSPARENT ) NTK_TextOut( hDC, 100, 230, "What do you think of that - my little boy !" ) NTK_SelectObject( hDC, hOldObj ) NTK_SetTextColor( hDC, nBlue ) NTK_TextOut( hDC, 100, 290, "Ooops, I hope Tux will not be too much shaken !!!" ) NTK_ENDPAINT( hWnd, aPS ) RETURN(0) CASE message == WM_DESTROY NTK_KillTimer(hWnd, hTimer) NTK_PostQuitMessage(0) RETURN(0) ENDCASE RETURN( NTK_DEFWNDPROC(hWnd, message, nwParam, nlParam) ) //RETURN -1 // OR NTK_DEFWNDPROC( ... ) is the same ! ****** ****************************************************************************************** ****** ****** ****** Handler for drawing purpose.. ****** ****** STATIC FUNCTION DoDrawRotationBmp( hWnd, hDC ) LOCAL hDcMem LOCAL hDcNew LOCAL hBmp LOCAL hBr LOCAL nDstX := 300 // Sets the width of the destination bitmap, indeed the default visualisation window size LOCAL nDstY := 300 // Sets the height of the destination bitmap, indeed the default visualisation window size LOCAL i, nOffset LOCAL aRt := ARRAY(4) LOCAL aRtmp := ARRAY(4) aRt := NTK_GetClientRect(hWnd) // First we draw the colored bars in the upper part of the window that serve as // reference/starting bitmap to rotate nOffset := (aRt[Rect_Right] - aRt[Rect_Left] - 200) / 2 aRtmp[Rect_Left] := nOffset aRtmp[Rect_Right] := nOffset + 1 aRtmp[Rect_Top] := 0 aRtmp[Rect_Bottom] := 200 FOR i = 0 TO 200 hBr := NTK_CreateSolidBrush( NTK_RGB(i * 8 % 255, i * 5 % 255, i * 2 % 255) ) NTK_FillRect( hDC,; aRtmp[Rect_Left], aRtmp[Rect_Top], aRtmp[Rect_Right], aRtmp[Rect_Bottom],; hBr ) NTK_DeleteObject(hBr) aRtmp[Rect_Left]++ aRtmp[Rect_Right]++ NEXT // Just add our favorite Tux pinguin inside the starting Bitmap... NTK_DrawBmp( hDC, hTuxBmp, nOffset+075, 050, SRCCOPY ) // We use NTK_BitBlt() to grab & store the refrence/starting Bitmap into a memory HDC hDcNew := NTK_CreateCompatibleDC(hDC) hBmp := NTK_CreateCompatibleBitmap(hDC, 200,200) NTK_SelectObject(hDcNew, hBmp) NTK_BitBlt(hDcNew, 0, 0, 200, 200, hdc, (aRt[Rect_Right] - aRt[Rect_Left] - 200) / 2, 0, SRCCOPY) // We create the new memory DC for destination Bitmap hDcMem := NTK_CreateCompatibleDC(hDcNew) // Now, let's go rotate that memory HDC . Ooops, I hope Tux will not be too much shaken !!! NTK_RotateMemoryDC(hBmp, hDcNew, 200, 200, nBmpAngle, hDcMem, nDstX, nDstY) NTK_DeleteObject(hBmp) NTK_DeleteDC(hDcNew) // Create the output HDC hDcNew := NTK_CreateCompatibleDC(hDC) hBmp := NTK_CreateCompatibleBitmap(hDC, 400,400) NTK_SelectObject(hDcNew, hBmp) aRtmp[Rect_Left] := 0 aRtmp[Rect_Top] := 0 aRtmp[Rect_Right] := 400 aRtmp[Rect_Bottom] := 400 // Fill the output HDC with the window background color and BitBlt the rotated bitmap into it NTK_FillRect( hDcNew,; aRtmp[Rect_Left], aRtmp[Rect_Top], aRtmp[Rect_Right], aRtmp[Rect_Bottom],; NTK_GetSysColorBrush(COLOR_WINDOW) ) NTK_BitBlt( hDcNew, (400 - nDstX) / 2, (400-nDstY) / 2, nDstX, nDstY, hdcMem, 0, 0, SRCCOPY ) NTK_DeleteDC(hDcMem) NTK_BitBlt( hDC, (aRt[Rect_Left] + aRt[Rect_Right] - 400) / 2, aRt[Rect_Bottom] - 400, 400, 400, hDcNew, 0, 0, SRCCOPY ) NTK_DeleteObject(hBmp) NTK_DeleteDC(hDcNew) RETURN(Nil) ****** ****** ******