WORK IN PROGRESS
This is the fourth post of a serie, where I shall try to explain how to take complete control over SDI window.
With this one, the full border frame has been completed, with the addition of caption, status led, and icon.
Like with standard caption you can use double click to maximize / restore the window.
You will notice that both Led and Caption text color are changing to match the window 's focus.
In this version most of the changes have been done to the main WndProc to handle the different states of the window.
See:
CASE %WM_GETMINMAXINFO
CASE %WM_SETTEXT
CASE %WM_NCLBUTTONDBLCLK
CASE %WM_NCACTIVATE
See also the changes that have been done there:
SUB zPaintBackground()
'// Draw text using GDIPLUS on any DC
FUNCTION zDrawTextToDC( _
BYVAL hDC AS LONG, _
zUseText AS ASCIIZ, _
BYVAL x AS LONG, _
BYVAL y AS LONG, _
BYVAL ColrARGB AS LONG, _
zUseFont AS ASCIIZ, _
BYVAL UseSize AS LONG, _
BYVAL Use3D AS LONG, _
BYVAL UseStrFormat AS LONG) AS LONG
LOCAL layoutRect AS RECTF
LOCAL boundingBox AS RECTF
LOCAl nRet, graphics, strFormat, Fam, TempFont, zdW, zdH AS LONG
LOCAL sUseText, sUseFont, sCaption AS STRING
sUseText = zUseText: sUseFont = zUseFont
' Create matching font
CALL GdipCreateFontFamilyFromName((UCODE$(sUseFont)), 0, Fam)
IF Fam THEN
CALL GdipCreateFont(Fam, UseSize, %FontStyleRegular, %UnitPixel, TempFont)
IF TempFont THEN
' Shadow offset use NULL if you don't want a shadow,
' use positive value to display shadow right, negative value to display shadow left
' Draw the string
CALL GdipCreateStringFormat(0, 0, strFormat)
CALL GdipCreateFromHDC(hDC, graphics)
sCaption = TRIM$(sUseText, ANY CHR$(0,32))
CALL GdipMeasureString(graphics, (UCODE$(sCaption)), LEN(sCaption), TempFont, layoutRect, strFormat, boundingBox, BYVAL %NULL, BYVAL %NULL)
CALL GdipDeleteStringFormat(strFormat)
zdW = CLNG(boundingBox.nRight + .5)
zdH = CLNG(boundingBox.nBottom + 1.5)
nRet = zDrawStringFormatedEx(graphics, _
sUseText, _
x, y, _
zdW, zdH, _
ColrARGB, _
%TextRenderingHintAntiAlias, _
TempFont, _
Use3D, _
UseStrFormat)
CALL GdipDeleteGraphics(graphics)
CALL GdipDeleteFont(TempFont) ' Delete the font object
END IF
CALL GdipDeleteFontFamily(Fam) ' Delete the font family object
END IF
FUNCTION = nRet
END FUNCTION
'// Render GDIPLUS string into graphics
FUNCTION zDrawStringFormatedEx(BYVAL graphics AS LONG, BYVAL sTxt AS STRING, _
BYVAL x AS LONG, BYVAL y AS LONG, BYVAL xWidth AS LONG, BYVAL yHeight AS LONG, _
BYVAL ColrARGB AS LONG, BYVAL TextRendering AS LONG, BYVAL curFont AS LONG, _
BYVAL ShadowOffSet AS LONG, BYVAL UseStrFormat AS LONG) AS LONG
LOCAL rcLayout AS RECTF
LOCAl nRet, brush, strFormat AS LONG
nRet = -1
IF graphics THEN
IF UseStrFormat THEN
SWAP xWidth, yHeight
IF UseStrFormat = %ZD_TextVertUp THEN
CALL GdipTranslateWorldTransform(graphics, 0, y + yHeight, %MatrixOrderPrepend)
CALL GdipRotateWorldTransform(graphics, 270, %MatrixOrderPrepend)
ELSE
CALL GdipCreateStringFormat(0, 0, strFormat)
CALL GdipSetStringFormatFlags(strFormat, UseStrFormat)
END IF
END IF
CALL GdipSetTextRenderingHint(graphics, TextRendering)
IF ShadowOffset THEN
' Create a brush for the text shadow with
CALL GdipCreateSolidFill(zColorARGB(128, 0), brush)
' Set up a drawing area for the shadow
' NOTE: Leaving the right and bottom values at zero means there is no boundary
rcLayout.nLeft = x + ShadowOffset
rcLayout.nTop = y + ShadowOffset
IF UseStrFormat = %ZD_TextVertUp THEN
rcLayout.nLEFT = 0 - ABS(ShadowOffset)
rcLayout.nTop = x + ShadowOffset
rcLayout.nRIGHT = yHeight: rcLayout.nBottom = xWidth
END IF
nRet = GdipDrawString(graphics, (UCODE$(sTxt)), LEN(sTxt), curFont, rcLayout, strFormat, brush)
' Cleanup
CALL GdipDeleteBrush(brush)
END IF
CALL GdipCreateSolidFill(ColrARGB, brush)
rcLayout.nLeft = x: rcLayout.nTop = y
rcLayout.nRight = xWidth: rcLayout.nBottom = yHeight
IF UseStrFormat = %ZD_TextVertUp THEN
rcLayout.nLEFT = 0: rcLayout.nTop = x
rcLayout.nRIGHT = yHeight: rcLayout.nBottom = xWidth
END IF
nRet = GdipDrawString(graphics, (UCODE$(sTxt)), LEN(sTxt), curFont, rcLayout, strFormat, brush)
' Cleanup
IF UseStrFormat THEN
IF UseStrFormat = %ZD_TextVertUp THEN
CALL GdipResetWorldTransform(graphics)
ELSE
CALL GdipDeleteStringFormat(strFormat)
END IF
END IF
CALL GdipDeleteBrush(brush)
END IF
FUNCTION = nRet
END FUNCTION
So far the user is able to move the window from background, but I could limit dragging to the caption only, like in Microsoft "standard".
Your thought?
Superb!
Add transparency and ... wow! PowerVista is there!
TRANSPARENCY,
well I have done it already for C# and WinDev, I think I could do it for PB as well 8)
The solution is to use: 2 popup windows within a single form!
one transparent to figure the non-client area, and the oher one opaque to match the client area and the system buttons (using region).
As you can imagine not very simple, however the result looks very good.
Things would be easier if I could use true compositing like in VISTA.
Note: on XP there is in theory an extended style that could help doing it, WS_EX_COMPOSITED, painting from bottom to top, but unfortunatly it doesn't work well, mainly because very few programmers know how to use the wm_print and wm_printclient messages.
I have this code to make DDT dialogs transparent.
#COMPILE EXE
#INCLUDE "WIN32API.INC"
%TranslucenceLevel = 170
%GWL_EXSTYLE = (-20)
%WS_EX_LAYERED = &H80000
%LWA_ALPHA = &H2
%AlphaLevel = 20
CALLBACK FUNCTION DlgProc()
SELECT CASE CBMSG
CASE %WM_INITDIALOG
SetWindowLong CBHNDL, %GWL_EXSTYLE, GetWindowLong(CBHNDL, %GWL_EXSTYLE)OR %WS_EX_LAYERED
SetLayeredWindowAttributes CBHNDL, 0, %TranslucenceLevel, %LWA_ALPHA
FUNCTION = 1
END SELECT
END FUNCTION
FUNCTION PBMAIN () AS LONG
GLOBAL Result AS LONG
GLOBAL hWnd AS DWORD
DIALOG NEW %HWND_DESKTOP, "Transparent Form",,, 365, 250, %WS_POPUP OR %WS_VISIBLE OR %WS_CLIPCHILDREN OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX, 0 TO hWnd
DIALOG SHOW MODAL hWnd, CALL DlgProc
END FUNCTION
Eros,
I know already how to use the SetLayeredWindowAttributes, see example below
(http://www.zapsolution.com/preview/vista.png)
Just need to translate it into plain SDK ...
However thank you for the DDT code. ;)
Note: If any one feel comfortable with both C# and gdiplus, and want to contribute to this project, then I have a nice "AERO GLASS BUTTON like" to translate from managed code into PB.
See screen shot there:
(http://www.codeproject.com/cs/miscctrl/glassbutton/glassbutton1.png)
Sorry Patrice,
I know you are the guru here (not joking, I'm serious).
I just posted in case other users needs it. It is just few lines.
Looking at this post with all those nice images and the power Patrice put on it ... it comes to my mind what could have been the official Power Basic forum with a more serious forum software.
Eros
Hi,
that samples look cool.
Regarding last window ... isn't the text info in lowest right corner in Polish language ?
Quite easy to translate except "skladnik" :)
Bye,
Petr
Petr,
Quote
Regarding last window ... isn't the text info in lowest right corner in Polish language ?
Yes, it is ;D
QuoteQuite easy to translate
Original C# source code is there:
C# source code (http://www.codeproject.com/cs/miscctrl/glassbutton.asp)
;D
I'm sorry Patrice, with translate I meant that Polish sentence, not C# :-[
Petr
Patrice your articles got me into studying the winApi in powerBasic. Hence my low profile lately and for some time to come. It seems daunting to get through, but when you see the type of results that can be achieved as you have shown it motivates one to study.
The first post of this thread has been updated, to fix the ZIP file corruption caused by the "Server Collapse".
...