I have this little code in drawing some filled squares:
hPen = CreatePen(%PS_SOLID, 1, &HFFFFFF)
hPen = SelectObject(memDC, hPen)
' RoundRect memDC, LT, LT, rc.nright - RB, rc.nbottom - RB, '@rr.corner, @rr.corner
RoundRect memDC, LT, LT, rc.nright , rc.nbottom , @rr.corner, @rr.corner
But i would rather have it draw the colour of the background.
The square will be invisible to the user, but it hosts an image which i want the user to see.
(this is part of a button control)
The first line of this code must be changed to the background colour. I know Paul uses something like that in a Label by determining the first pixel colour.
its a bit new to me. How does one determine that pixel colour? (Since i do have the coordinates already it shouldnt be that hard, I think?)
Local PCol As Long 'Pixel Color
Local hDC As Dword
Local p As PointApi
hDC = GetDC(hWndForm)
GetCursorPos p 'Could use hard-coded values of course
PCol = GetPixel(hDC, p.x, p.y)
But reading what you are trying to do, you really need to set the background of your image to transparent. Then the color below will show though.
Back from a little roadtrip...
I think i am going to make a mess here.
I have slightly modified that line from the RRbutton in its .inc file.
The button is indeed transparent, but it need the lines it draws around the button to be either the same colour as the object below it or have them no colour at all, if that can be done..?
I am emulating the new windows buttons in win10 which has no lines and merely changes the icon inside to another colour.
Much of this is done by the RR button, but i had to remove a line to make this work 90%
Works like a dream on a white background, but obviously anything else shows the white lines.
The button wont function unless it draws the rect, but can one make lines invisible?
Changing from %ps_solid to %ps_null only removes one side from the button.
I wonder if Borje Hagsten who made the control will be happy with me trying to mod it?
I am having a good laugh at myself here... I am so going to mess this up :)
Quote
The square will be invisible to the user, but it hosts an image which i want the user to see.
(this is part of a button control)
Make the button ownerdraw and just draw the image...
' ########################################################################################
' Microsoft Windows
' File: CW_ButtonOwnerdraw.pbtpl
' Contents: Template - CWindow with a ownerdraw button
' Compilers: PBWIN 10+, PBCC 6+
' Headers: Windows API headers III
' Copyright (c) 2016 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%UNICODE = 1
' // Include files for external files
#INCLUDE ONCE "CWindow.inc" ' // CWindow class
%IDC_BUTTON = 100
' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG
' // Set process DPI aware
AfxSetProcessDPIAware
' // Create an instance of the class
LOCAL pWindow AS IWindow
pWindow = CLASS "CWindow"
IF ISNOTHING(pWindow) THEN EXIT FUNCTION
' // Create the main window
' // Note: CW_USEDEFAULT is used as the default value When passing 0's as the width and height
pWindow.CreateWindow(%NULL, "CWindow with ownerdraw button", 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
' // Set the client size
pWindow.SetClientSize 500, 320
' // Center the window
pWindow.CenterWindow
' // Add a button
LOCAL hButton AS DWORD
hButton = pWindow.AddButton(pWindow.hwnd, %IDC_BUTTON, "&Ownerdraw button", 300, 150, 50, 50, %WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW)
SetFocus hButton
' // Default message pump (you can replace it with your own)
FUNCTION = pWindow.DoEvents(nCmdShow)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
STATIC pWindow AS IWindow ' // Reference to the IWindow interface
STATIC hBitmap AS DWORD
' // Process window mesages
SELECT CASE uMsg
CASE %WM_CREATE
' // Get a reference to the IWindow interface from the CREATESTRUCT structure
pWindow = CWindow_GetObjectFromCreateStruct(lParam)
hBitmap = LoadImage(%NULL, EXE.PATH$ & "smallface.bmp", _ ' --> change me!
%IMAGE_BITMAP, AfxScaleX(50), AfxScaleY(50), %LR_LOADFROMFILE)
EXIT FUNCTION
CASE %WM_COMMAND
SELECT CASE LO(WORD, wParam)
CASE %IDCANCEL
' // If the Escape key has been pressed...
IF HI(WORD, wParam) = %BN_CLICKED THEN
' // ... close the application by sending a WM_CLOSE message
SendMessage hwnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
CASE %IDC_BUTTON
MSGBOX "Button clicked"
EXIT FUNCTION
END SELECT
CASE %WM_DRAWITEM
LOCAL pDis AS DRAWITEMSTRUCT PTR
pDis = lParam
IF @pDis.CtlId <> %IDC_BUTTON THEN EXIT FUNCTION
IF hBitmap THEN DrawState @pDis.hDC, 0, 0, hBitmap, 0, 0, 0, 0, 0, %DST_BITMAP
FUNCTION = %TRUE
EXIT FUNCTION
CASE %WM_DESTROY
IF hBitmap THEN DeleteObject hBitmap
' // End the application
PostQuitMessage 0
EXIT FUNCTION
END SELECT
' // Pass unprocessed messages to Windows
FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
Quote from: Petrus Vorster on April 11, 2016, 01:45:03 PM
I am having a good laugh at myself here... I am so going to mess this up :)
Don't make things harder that they need to be...
Hi Jose
Thanks Jose.
Now, if i need to change the Icon on the in/out movement of the mouse, how do one go about doing that?
If one look at how many programs looks like nowadays, using vector icons, one will see perhaps a black line icon, but it changes when the mouse enters the button face, much like the RR-button does, except they no longer draw the lines around the buttons.
Programmers knows that all this "bells and whistles" has nothing to do with program performance, but users buy with their eyes and minds. If the looks isn't up to date then people already assume lower performance. I dont sell programs, but i also like the users to have something that looks great too. :)
> Now, if i need to change the Icon on the in/out movement of the mouse, how do one go about doing that?
That's more complicated. You may need to subclass the button, check for the WM_MOUSEMOVE and WM_MOUSELEAVE messages, track the mouse movement, etc.
Look at the code of RR_BUTTON or my XPBUTTON control.
This example subclasses the ownerdraw button, changes the image when the mouse enters in it and restores the first image when the mouse leaves it.
' ########################################################################################
' Microsoft Windows
' File: CW_ButtonOwnerdraw.pbtpl
' Contents: Template - CWindow with a ownerdraw button
' Compilers: PBWIN 10+, PBCC 6+
' Headers: Windows API headers III
' Copyright (c) 2014 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%UNICODE = 1
' // Include files for external files
#INCLUDE ONCE "CWindow.inc" ' // CWindow class
%IDC_BUTTON = 100
' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG
' // Set process DPI aware
AfxSetProcessDPIAware
' // Create an instance of the class
LOCAL pWindow AS IWindow
pWindow = CLASS "CWindow"
IF ISNOTHING(pWindow) THEN EXIT FUNCTION
' // Create the main window
' // Note: CW_USEDEFAULT is used as the default value When passing 0's as the width and height
pWindow.CreateWindow(%NULL, "CWindow with subclassed ownerdraw button", 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
' // Set the client size
pWindow.SetClientSize 500, 320
' // Center the window
pWindow.CenterWindow
' // Add a button
LOCAL hButton AS DWORD
hButton = pWindow.AddButton(pWindow.hwnd, %IDC_BUTTON, "&Ownerdraw button", 300, 150, 50, 50, _
%WS_VISIBLE OR %WS_TABSTOP OR %BS_OWNERDRAW, 0, CODEPTR(TextBtn_SubclassProc))
SetFocus hButton
' // Default message pump (you can replace it with your own)
FUNCTION = pWindow.DoEvents(nCmdShow)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
STATIC pWindow AS IWindow ' // Reference to the IWindow interface
STATIC hBitmap1, hBitmap2 AS DWORD
' // Process window mesages
SELECT CASE uMsg
CASE %WM_CREATE
' // Get a reference to the IWindow interface from the CREATESTRUCT structure
pWindow = CWindow_GetObjectFromCreateStruct(lParam)
hBitmap1 = LoadImage(%NULL, EXE.PATH$ & "smallface.bmp", _ ' --> change me!
%IMAGE_BITMAP, AfxScaleX(50), AfxScaleY(50), %LR_LOADFROMFILE)
hBitmap2 = LoadImage(%NULL, EXE.PATH$ & "cowgirl.bmp", _ ' --> change me!
%IMAGE_BITMAP, AfxScaleX(50), AfxScaleY(50), %LR_LOADFROMFILE)
EXIT FUNCTION
CASE %WM_COMMAND
SELECT CASE LO(WORD, wParam)
CASE %IDCANCEL
' // If the Escape key has been pressed...
IF HI(WORD, wParam) = %BN_CLICKED THEN
' // ... close the application by sending a WM_CLOSE message
SendMessage hwnd, %WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
END SELECT
CASE %WM_DRAWITEM
LOCAL pDis AS DRAWITEMSTRUCT PTR
pDis = lParam
IF @pDis.CtlId <> %IDC_BUTTON THEN EXIT FUNCTION
IF GetPropW(GetDlgItem(hwnd, %IDC_BUTTON), "HOT") = 0 THEN
IF hBitmap1 THEN DrawState @pDis.hDC, 0, 0, hBitmap1, 0, 0, 0, 0, 0, %DST_BITMAP
ELSE
IF hBitmap2 THEN DrawState @pDis.hDC, 0, 0, hBitmap2, 0, 0, 0, 0, 0, %DST_BITMAP
END IF
FUNCTION = %TRUE
EXIT FUNCTION
CASE %WM_DESTROY
IF hBitmap1 THEN DeleteObject hBitmap1
IF hBitmap2 THEN DeleteObject hBitmap2
' // End the application
PostQuitMessage 0
EXIT FUNCTION
END SELECT
' // Pass unprocessed messages to Windows
FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Processes messages for the subclassed Button window.
' ========================================================================================
FUNCTION TextBtn_SubclassProc ( _
BYVAL hwnd AS DWORD, _ ' // Control window handle
BYVAL uMsg AS DWORD, _ ' // Type of message
BYVAL wParam AS DWORD, _ ' // First message parameter
BYVAL lParam AS LONG _ ' // Second message parameter
) AS LONG
SELECT CASE uMsg
CASE %WM_GETDLGCODE
' // All keyboard input
FUNCTION = %DLGC_WANTALLKEYS
EXIT FUNCTION
CASE %WM_LBUTTONDOWN
MessageBoxW(GetParent(hwnd), "Click", "", %MB_OK)
EXIT FUNCTION
CASE %WM_KEYDOWN
SELECT CASE LO(WORD, wParam)
CASE %VK_ESCAPE
SendMessageW(GetParent(hwnd), %WM_CLOSE, 0, 0)
EXIT FUNCTION
END SELECT
CASE %WM_MOUSEMOVE
' // Tracks the mouse movement and stores the hot state
LOCAL trackMouse AS TRACKMOUSEEVENTAPI
IF GetPropW(hwnd, "HOT") = 0 THEN
trackMouse.cbSize = SIZEOF(trackMouse)
trackMouse.dwFlags = %TME_LEAVE
trackMouse.hwndTrack = hwnd
trackMouse.dwHoverTime = 1
TrackMouseEvent(trackMouse)
SetPropW hwnd, "HOT", %TRUE
InvalidateRect hwnd, BYVAL %NULL, 0
UpdateWindow hwnd
END IF
EXIT FUNCTION
CASE %WM_MOUSELEAVE
' // Removes the hot state and redraws the button
RemovePropW hwnd, "HOT"
InvalidateRect hwnd, BYVAL %NULL, 0
UpdateWindow hwnd
EXIT FUNCTION
CASE %WM_DESTROY
' // REQUIRED: Remove control subclassing
SetWindowLong hwnd, %GWL_WNDPROC, RemoveProp(hwnd, "OLDWNDPROC")
END SELECT
FUNCTION = CallWindowProc(GetProp(hwnd, "OLDWNDPROC"), hwnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
Thanks a million Josè!
I just solved the mod on the rr button too, and it works just fine.
Thanks for the patience and advice everyone.