Powerbasic Museum 2020-B

IT-Consultant: Patrice Terrier => SDK Programming => Topic started by: Patrice Terrier on August 11, 2007, 01:35:45 PM

Title: [SDK] 05 - Take control of your BUTTONS
Post by: Patrice Terrier on August 11, 2007, 01:35:45 PM
WORK IN PROGRESS
This is the fifth post of a serie, where I shall try to explain how to take complete control over SDI window.

This is a major release, because most of the basic functions I wanted to put in, are now there.

You can now create three type of buttons

1 - zButImage

2 - zPushButton

3 - zFrameButton

With small modifications it could be possible to create more, like ckeck box or radio button, using the "ZBUTIMAGE" class.

You can even use zFrameButton to draw a static image.

I have added a new temporary double buffer, that can be used to remove flickering when drawing complex child controls.

'// Create temporary double buffer

FUNCTION zDoubleBuffer(BYVAL hDC AS LONG, BYVAL x AS LONG, BYVAL y AS LONG, BYVAL Action AS LONG) STATIC AS LONG
    DIM Xx AS LONG, Yy AS LONG, UseDC AS LONG, hDCTemp AS LONG, hBMTemp AS LONG, hBMPrev AS LONG
    IF Action THEN
     ' Create OFF screen bitmap to avoid flickering and allow smooth display
     ' ---------------------------------------------------------------------
       hDCTemp = CreateCompatibleDC(hDC)
       hBMTemp = CreateCompatibleBitmap(hDC, x, y)
       hBMPrev = SelectObject(hDCTemp, hBMTemp)
       Xx = x: Yy = y
       UseDC = hDC
       FUNCTION = hDCTemp
    ELSE
     ' End of OFF screen drawing, fast BitBlt to the target display Window
     ' -------------------------------------------------------------------
     ' Draw final result to the target window
       CALL BitBlt(UseDC, x, y, Xx, Yy, hDCTemp, 0, 0, %SRCCOPY)
     ' Deallocate system resources
       CALL SelectObject(hDCTemp, hBMPrev)
       CALL DeleteObject(hBMTemp)
       CALL DeleteDC(hDCTemp)
       FUNCTION = 0
    END IF

END FUNCTION

 
The %ANCHOR_CENTER_HORZ_BOTTOM has been enhanced, you can see it on the multimedia buttons as well as the frame button drawn arround them, when you resize the form.

All images have been reworked to use transparent opacity and little shadow to give your form a professionnal look like this one:

(http://www.zapsolution.com/pictures/sdk/zskin05.png)

Nice isn't it ?

Patrice Terrier
www.zapsolution.com
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Theo Gottwald on August 11, 2007, 01:47:17 PM
That Button is really state-of-the-art. They are just perfect in design!
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: José Roca on August 11, 2007, 02:10:55 PM
 
¡Bravo, maestro! Hats off to you!
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Petr Schreiber on August 11, 2007, 02:30:12 PM
Hi Patrice,

it isn't nice, it is beautiful !


Thanks,
Petr
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Eros Olmi on August 11, 2007, 02:45:06 PM
Well, a big thanks is not enough, really.
And best of all, source code is full of many little secrets to learn from and master  :o

Thanks!
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Patrice Terrier on August 11, 2007, 03:01:04 PM
QuoteAnd best of all, source code is full of many little secrets to learn from and master

Yep, very few programmers are knowing these little secrets, except you now, of course ;)

More to come...
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Eros Olmi on August 11, 2007, 03:20:12 PM
You mean I was the only one not to know all those secrets?
Oh no, I'm always the last one to know things! :P
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Kent Sarikaya on August 12, 2007, 12:41:56 AM
Beautiful look to the window and controls, it is as beautiful as the api coding is long, I guess no shortcuts to beauty :)
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Patrice Terrier on August 12, 2007, 09:00:07 AM
Quoteit is as beautiful as the api coding is long

This is because I choose to put everyting in the EXE for the tutorial pupose, however usually most of classes coding are done in DLL (see the size of the Windows API's DLLs).

Ultimatly most of the code should be moved into a DLL, where some more nice stuffs can be done, that couldn't be done in a EXE, like low level advanced  hooking functions.

Example of thing that can be done only with a DLL:

FUNCTION HookFunction (hLib AS DWORD, Func AS STRING, HookProc AS DWORD, OrigProc AS DWORD) AS LONG
    LOCAL lpImageDosHeader          AS IMAGE_DOS_HEADER PTR
    LOCAL lpImageNtHeaders          AS IMAGE_NT_HEADERS PTR
    LOCAL lpImageImportDescriptor   AS IMAGE_IMPORT_DESCRIPTOR PTR
    LOCAL lpImageImportByName       AS IMAGE_IMPORT_BY_NAME PTR
    LOCAL lpFuncNameRef             AS DWORD PTR
    LOCAL lpFuncAddr                AS DWORD PTR
    LOCAL flOldProtect              AS DWORD

    lpImageDosHeader = hLib

    IF @lpImageDosHeader.e_magic <> %IMAGE_DOS_SIGNATURE THEN EXIT FUNCTION ' invalid DOS signature
    lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
    IF @lpImageNtHeaders.Signature <> %IMAGE_NT_SIGNATURE THEN EXIT FUNCTION  ' invalid NT signature
    IF @lpImageNtHeaders.FileHeader.SizeOfOptionalHeader <> SIZEOF( @lpImageNtHeaders.OptionalHeader) OR _
       @lpImageNtHeaders.OptionalHeader.Magic <> %IMAGE_NT_OPTIONAL_HDR32_MAGIC THEN EXIT FUNCTION

    IF @lpImageNtHeaders.OptionalHeader.NumberOfRvaAndSizes <= %IMAGE_DIRECTORY_ENTRY_IMPORT THEN EXIT FUNCTION ' IMPORT section does not exist

    lpImageImportDescriptor = @lpImageNtHeaders.OptionalHeader.DataDirectory( %IMAGE_DIRECTORY_ENTRY_IMPORT ).VirtualAddress + lpImageDosHeader
    IF lpImageImportDescriptor = lpImageDosHeader THEN EXIT FUNCTION

    WHILE @lpImageImportDescriptor.OriginalFirstThunk <> 0
     ' DllName @lpImageImportDescriptor.pName + lpImageDosHeader = Asciiz Ptr
       lpFuncNameRef = @lpImageImportDescriptor.OriginalFirstThunk + lpImageDosHeader
       lpFuncAddr = @lpImageImportDescriptor.FirstThunk         + lpImageDosHeader

       DO WHILE @lpFuncNameRef <> 0
          lpImageImportByName = @lpFuncNameRef + lpImageDosHeader
          IF (@lpFuncNameRef AND %IMAGE_ORDINAL_FLAG) THEN

          ELSEIF @lpImageImportByName.ImpName = Func THEN
             IF VirtualProtect(BYVAL lpFuncAddr, 4, %PAGE_READWRITE, flOldProtect) = 0 THEN EXIT FUNCTION
             OrigProc = @lpFuncAddr: @lpFuncAddr = HookProc
             IF FlushInstructionCache(GetCurrentProcess, BYVAL @lpFuncAddr, 4) = 0 THEN EXIT FUNCTION
             IF flOldProtect <> %PAGE_READWRITE THEN VirtualProtect BYVAL lpFuncAddr, 4, flOldProtect, flOldProtect
             FUNCTION = 1: EXIT FUNCTION ' Success
          END IF
          INCR lpFuncNameRef
          INCR lpFuncAddr
       LOOP
       INCR lpImageImportDescriptor
    LOOP
END FUNCTION


The code above is being used to hook/replace existing API directly within Windows DLLs!

and here is an example that shows you how to use it, to replace the core API BeginPaint EndPaint by your own code.

Quote
FUNCTION GetMsgProc(BYVAL nCode AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG

   IF nCode < 0 THEN
      FUNCTION = CallNextHookEx(BYVAL hHook, BYVAL nCode, BYVAL wParam, BYVAL lParam)
   ELSEIF hHookDone = %FALSE THEN
      CALL HookFunction(GetModuleHandle(BYVAL %NULL), "BeginPaint", CODEPTR(skBeginPaint), hBeginPaint)
      CALL HookFunction(GetModuleHandle(BYVAL %NULL), "EndPaint", CODEPTR(skEndPaint), hEndPaint)
      hHookDone = %TRUE
   END IF

END FUNCTION

FUNCTION zBeginPaint ALIAS "zBeginPaint" (BYVAL hWnd AS LONG, ps AS PAINTSTRUCT) EXPORT AS LONG
    LOCAL rw AS RECT
    LOCAL pt AS POINTAPI
    Item& = skChild(hWnd&)
    IF Item& THEN
       hOwner& = skPopupOwner(hWnd&)
       OwnerItem& = skItem(hOwner&)
       IF OwnerItem& THEN
          IF Win(OwnerItem&).MemDC THEN
             ps.hDC = Win(OwnerItem&).MemDC
             ps.fErase = 0

             CALL GetWindowRect(hOwner&, rw)
             pt.X = 0: pt.Y = 0: CALL ClientToScreen(hWnd&, pt)
             ofX& = pt.X - rw.nLeft: ofY& = pt.Y - rw.nTop
             CALL GetClientRect(hWnd&, rw)

             ps.rcPaint.nLeft   = ofX&
             ps.rcPaint.nTop    = ofY&
             ps.rcPaint.nRight  = ofX& + rw.nRight
             ps.rcPaint.nBottom = ofY& + rw.nBottom

             ps.fRestore   = 0
             ps.fIncUpdate = 0
             FOR K& = 0 TO 31: ps.rgbReserved(K&) = 0: NEXT
             FUNCTION = ps.hDC
             EXIT FUNCTION
          END IF
       END IF
    END IF
    CALL DWORD hBeginPaint USING BeginPaint (hWnd, ps) TO Ret&
    FUNCTION = Ret&

END FUNCTION

Of course this kind of thing requires a very good knowledge of the core API, and you must know exactly what you are doing or be assured that you will crash your computer.
:'(

This is one of the reason why Microsoft put ahead managed code, to protect the OS from direct access to the low level FLAT API engine, no more hackers/hookers there  :)


PS: The BeginPaint EndPaint hook function is a quick cut and past from my WinLIFT SkinEngine, that was written 10 years ago!

Patrice Terrier
www.zapsolution.com
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Edwin Knoppert on August 12, 2007, 10:30:39 AM
I wonder if HookFunction() is valid on kernel32.exe api's
Afaik this is a special 'lib' which is shared among apps.

I might be wrong.

Otherwise thanks for this one.
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Patrice Terrier on August 12, 2007, 11:11:50 AM
Edwin,

QuoteI wonder if HookFunction() is valid on kernel32.exe api's Afaik this is a special 'lib' which is shared among apps.

From my own experiencs all the hook functions being used in my DLLs are working with all Windows flavor including VISTA.

By the way Edwin, did you remember this Browse For Folder function, we have been working together with you and Semen, would you mind if I post its source code there?

I would like to make this board, a kind of SDK's Gurus code section ;)
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Edwin Knoppert on August 12, 2007, 01:10:25 PM
That code was rewritten and embedded into PwrDev.
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Patrice Terrier on August 12, 2007, 01:48:28 PM
Hi Edwin

I also rewrite it myself with drag & drop capabilities

May be we have done the same work twice ;)
Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Edwin Knoppert on August 20, 2007, 09:35:56 AM
I was testing hooking "CreateFileA" on my XP computer but no result.
A list build via @lpImageImportByName.ImpName shows NtCreateFile and openfile and such.
These might be the actual functions and even unicode.

My function calls CreateFileA though.

Any ideas?
I am not sure if using a simple getprocaddress() on the last part (below: ElseIf @lpImageImportByName.ImpName = Func Then ) wouldn't be sufficient.

Title: Re: [SDK] 5 - Take control of your BUTTONS
Post by: Patrice Terrier on August 20, 2007, 11:06:46 AM
Edwin

If hooking fails, then you could try the very advanced features like "detours" or "trampolin"
PDF document there: Binary interception of Win32 functions (http://research.microsoft.com/~galenh/Publications/HuntUsenixNt99.pdf)

Patrice Terrier
www.zapsolution.com
Title: Re: [SDK] 05 - Take control of your BUTTONS
Post by: Patrice Terrier on August 10, 2011, 05:12:45 PM
The first post of this thread has been updated, to fix the ZIP file corruption caused by the "Server Collapse".

...