Dear all,
How can I place my clock program to overlap the windows clock control?.
Printable View
Dear all,
How can I place my clock program to overlap the windows clock control?.
This may give you some idea.
Edit 1:
Or
[NotTested]
You can get the clock's hWnd by FindWindow/FindWindowEx APIs.
Using that hWnd, you can get the clock window's size by GetWindowRect API.
Then, you can place your form on top of it, or even set your form as a child form of the clock by using SetParent API.
(you may also need SetWindowPos API to make your form topmost.
You can get all those API declarations from http://www.allapi.net/
[/NotTested]
Edit 2: May be there is another better way to accomplish this by using shell DeskBand objects. I've never tried this. But from the screeshots looks like, this app uses DeskBand.
I am using this code to find the window handle of system clock.But the handle (bwnd)returns zero only. I don't know why.Pls help
VB Code:
Const WS_CHILD = &H40000000 Const WM_LBUTTONDOWN = &H201 Const WM_LBUTTONUP = &H202 Const SW_HIDE = 0 Const SW_NORMAL = 1 Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long Private Declare Function DestroyWindow Lib "user32" (ByVal hwnd As Long) As Long Dim tWnd As Long, bWnd As Long, ncWnd As Long Private Sub Form_Load() 'KPD-Team 1998 'URL: [url]http://www.allapi.net/[/url] 'E-Mail: [email][email protected][/email] Dim R As RECT 'Get the taskbar's window handle 'TrayClockWClass tWnd = FindWindow("Shell_TrayWnd", vbNullString) 'tWnd = FindWindow("TrayClockWClass", vbNullString) 'Get the start-button's window handle bWnd = FindWindowEx(tWnd, ByVal 0&, "TrayClockWClass", vbNullString) 'Get the start button's position GetWindowRect bWnd, R 'Create a new button End Sub
try this ..
VB Code:
tWnd = FindWindow("Shell_TrayWnd", vbNullString) bWnd = FindWindowEx(tWnd, ByVal 0&, "TrayNotifyWnd", vbNullString) ncWnd = FindWindowEx(bWnd, ByVal 0&, "TrayClockWClass", vbNullString) Debug.Print tWnd & "-" & bWnd & "-" & ncWnd
Thanks Rory,
It is working now.
Cool .. whats your code after GetWindowRect for positioning the form?
Just curious .. thanks.
I am facing problem setting the program always on top. I am using the follwing code to set the form top most always.
VB Code:
SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_SHOWWINDOW Or SWP_NOMOVE Or SWP_NOSIZE
I have placed my form over the windows clock control. While Displaying If click the taskbar the form goes invible.
I use just 2 constants instead of 4 and never had a problem. Try using just nosize, nomove constants
I use the following,Even the problem is there
VB Code:
SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
Sorry for not replying earlier. :o I was busy.
I prefer hooking. That way, you'll be able to listen to any other messages ( like context menu, time change, taskbar moving etc).
But if you don't like hooking, try the following code.
Looks like Set/GetWindowPlacement is easier than GetwindowRect. :D
VB Code:
Option Explicit ' [b][color=red]Custom Tray Clock[/color][/b] ' Set the form's border style to None. ' Add a timer ' ' To unload the form, click it. ' Private Type POINTAPI x As Long y As Long End Type ' Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type ' Private Type WINDOWPLACEMENT Length As Long flags As Long showCmd As Long ptMinPosition As POINTAPI ptMaxPosition As POINTAPI rcNormalPosition As RECT End Type ' Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long Private Declare Function GetWindowPlacement Lib "user32" (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long Private Declare Function SetWindowPlacement Lib "user32" (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long ' Dim hShellTrayWnd As Long ' Taskbar hWnd Dim TrayNotifyWnd As Long ' SystemTray hWnd Public TrayClockWClass As Long ' TrayClock hWnd Dim ReBarWindow32 As Long ' Contains the "Quick Launch" and "Running Applications" toolbars ' Dim lParentOld As Long Dim wpTrayOld As WINDOWPLACEMENT Dim wpClockOld As WINDOWPLACEMENT Dim wpRebarOld As WINDOWPLACEMENT '========================================================================== ' [b]lWidth is the value we want to add (in pixels)[/b] Private Sub HijackTrayClock(lWidthIncrese As Long) ' Dim wpTray As WINDOWPLACEMENT Dim wpClock As WINDOWPLACEMENT Dim wpRebar As WINDOWPLACEMENT ' ' Find the SystemTray and Clock windows ==> hShellTrayWnd = FindWindow("Shell_TrayWnd", vbNullString) TrayNotifyWnd = FindWindowEx(hShellTrayWnd, ByVal 0&, "TrayNotifyWnd", vbNullString) TrayClockWClass = FindWindowEx(TrayNotifyWnd, ByVal 0&, "TrayClockWClass", vbNullString) ReBarWindow32& = FindWindowEx(hShellTrayWnd, 0&, "ReBarWindow32", vbNullString) ' ' Save current position of SystemTray and Clock ' We'll restore them when exiting ==> GetWindowPlacement TrayClockWClass, wpClockOld GetWindowPlacement TrayNotifyWnd, wpTrayOld GetWindowPlacement ReBarWindow32, wpRebarOld ' ' Resize the SystemTray ==> GetWindowPlacement TrayNotifyWnd, wpTray wpTray.rcNormalPosition.Left = wpTray.rcNormalPosition.Left - lWidthIncrese SetWindowPlacement TrayNotifyWnd, wpTray ' ' Resize the Clock ==> ' GetWindowPlacement TrayNotifyWnd, wpTray GetWindowPlacement TrayClockWClass, wpClock wpClock.rcNormalPosition.Right = wpClock.rcNormalPosition.Right + lWidthIncrese SetWindowPlacement TrayClockWClass, wpClock ' ' Resize QuickLaunch and RunningApplications toolbars ==> GetWindowPlacement ReBarWindow32, wpRebar wpRebar.rcNormalPosition.Right = wpRebar.rcNormalPosition.Right - lWidthIncrese SetWindowPlacement ReBarWindow32, wpRebar ' ' Place our form as a child of Clock==> lParentOld = SetParent(Me.hwnd, TrayNotifyWnd) SetWindowPlacement Me.hwnd, wpClock End Sub '========================================================================== Private Sub Form_Load() HijackTrayClock 100 Me.BackColor = &HC0C0FF Me.AutoRedraw = True Timer1.Interval = 1000 Me.Print Time End Sub '========================================================================== Private Sub Timer1_Timer() Me.Cls Me.Print Time End Sub '========================================================================== Private Sub Form_Click() Unload Me End Sub '========================================================================== Private Sub Form_Unload(Cancel As Integer) ' Restore all ==> SetParent Me.hwnd, lParentOld SetWindowPlacement TrayNotifyWnd, wpTrayOld SetWindowPlacement TrayClockWClass, wpClockOld SetWindowPlacement ReBarWindow32, wpRebarOld End Sub
VB Code:
Option Explicit Const WS_CHILD = &H40000000 Const WM_LBUTTONDOWN = &H201 Const WM_LBUTTONUP = &H202 Const SW_HIDE = 0 Const SW_NORMAL = 1 Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long Private Declare Function DestroyWindow Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Integer) As Integer Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Integer, ByVal X As Integer, ByVal Y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal bRepaint As Integer) As Integer Private Declare Sub SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) Const HWND_TOPMOST = -1 Const HWND_NOTOPMOST = -2 Const SWP_NOSIZE = &H1 Const SWP_NOMOVE = &H2 Const SWP_NOACTIVATE = &H10 Const SWP_SHOWWINDOW = &H40 Dim tWnd As Long, bWnd As Long, ncWnd As Long '// SET TO TOP Public Sub SetWindowToTop(ByVal plnghWnd As Long) SetWindowPos plnghWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_SHOWWINDOW Or SWP_NOMOVE Or SWP_NOSIZE End Sub Private Sub Form_Load() Dim R As RECT Dim lngX As Integer Dim lngY As Integer Dim lngW As Integer Dim lngH As Integer 'Get the clocks window handle tWnd = FindWindow("Shell_TrayWnd", vbNullString) bWnd = FindWindowEx(tWnd, ByVal 0&, "TrayNotifyWnd", vbNullString) ncWnd = FindWindowEx(bWnd, ByVal 0&, "TrayClockWClass", vbNullString) 'Get the clocks position GetWindowRect ncWnd, R lngX = R.Left * 15 lngY = R.Top * 15 lngW = (R.Right - R.Left) * 15 lngH = (R.Bottom - R.Top) * 15 Form1.Move lngX, lngY, lngW, lngH SetWindowToTop Form1.hwnd 'Label1.Caption = Time End Sub
how do you get the background color of the System Tray though ..?
In classic theme, it is vbButtonFace.
I don't know XP theme APIs. In XP theme, I tried hDCToPicture to get the clock's DC. But it gets the text too. :mad:
I can't find any way to delete the text, except changing every pixel.
I hope there is an API in XP theme library to do this.
Dear IFrank,
What is meant by hooking.Pls explain
Hooking is simply serving as a middle man between messages sent to windows.Quote:
Originally Posted by danasegarane
Example....
You click on the return key, this message is posted to a window.
Example 2 (with hooking)
You click on the return key, your program checks out the message, the message is posted to a window.
And also I want the width of the form to be little more bigger?/
if you use the code i posted then ..
lngX = R.Left * 15
lngY = R.Top * 15
lngW = (R.Right - R.Left) * 15 <--- This is the Width ..add to it like + 100 etc..
lngH = (R.Bottom - R.Top) * 15 <--- This is the Height ..
Form1.Move lngX, lngY, lngW, lngH
PS. you'll also have to adjust the X (left) Eg. .. -100
Dear Rory?,
The problem i face in your code is that when i click taskbar bar, the form goes invisible??
add a timer ..
Private Sub Timer1_Timer()
SetWindowToTop Form1.hwnd
Label1.Caption = Time
End Sub
I've edited the code to accomplish this.Quote:
Originally Posted by danasegarane
But, as the tray/clock will get resized when you resize the taskbar or due to WinXP's inactive tray icon hiding feature, you'll need to constantly poll the SystemTray and Clock's size fom a timer.
i still want to know how he's getting the color the same .. :)
I already posted about classic theme.Quote:
Originally Posted by rory
I found that, In XP theme Windows simply uses a bitmap.
Download Resource Hacker.
Go to C:\WINDOWS\Resources\Themes\Luna folder.
Open the luna.msstyles file in ResHacker.
See the *_TASKBAND* bitmaps.
Windows uses them in themed mode.
Another code update.
Added code to resize QuickLaunch and RunningApplications toolbars.
Taskbar buttons now resizes properly (without being cut off). :D
Dear IFrank,
Thanks for the code.But I am finding some difficulties.I want the resized clock to be Present. But Now the clock goes to original Position after some time.
I don't think you can do sizing correctly without hooking (and/or other methods to get SysTray's condition).
The size and position of systray (and clock) changes when,
the taskbar resizes
or an trayicon gets added or removed,
or user clicks the arrow button (XP) of system tray..etc.
We have to monitor all those cases.
As I mentioned in post#20, the best you can do without hooking is,
add another timer with very small interval to constantly get systray's position.
In the following code, I've added another timer (Timer2). Now, everytime the timer fires, it checks the window placement. If the window is resized, it restores back to original position.
Drag and resize the taskbar - it will work fine.
But click on the arrow button of systray or add/remove an icon fron systray, you'll see the problem. I have never tried to get systray icon info. (My clock app doesn't resize. ;)) see if this code helps you.
Code 2: track sizechangeusing timer.
VB Code:
Option Explicit ' [b][color=red]Custom Tray Clock 2[/color][/b] ' Set the form's border style to None. ' Add 2 timers ' Private Type POINTAPI x As Long y As Long End Type ' Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type ' Private Type WINDOWPLACEMENT Length As Long flags As Long showCmd As Long ptMinPosition As POINTAPI ptMaxPosition As POINTAPI rcNormalPosition As RECT End Type ' Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long Private Declare Function GetWindowPlacement Lib "user32" (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long Private Declare Function SetWindowPlacement Lib "user32" (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long ' Dim hShellTrayWnd As Long ' Taskbar hWnd Dim TrayNotifyWnd As Long ' SystemTray hWnd Public TrayClockWClass As Long ' TrayClock hWnd Dim ReBarWindow32 As Long ' Contains the "Quick Launch" and "Running Applications" toolbars ' Dim lParentOld As Long Dim wpTrayOld As WINDOWPLACEMENT Dim wpClockOld As WINDOWPLACEMENT Dim wpRebarOld As WINDOWPLACEMENT ' Dim wpTray As WINDOWPLACEMENT Dim wpClock As WINDOWPLACEMENT Dim wpRebar As WINDOWPLACEMENT ' [b]lWidth is the value we want to add (in pixels)[/b] Private Sub HijackTrayClock(lWidthIncrese As Long) GetHwnd SaveOriginalPlacement Call ResizeClock(lWidthIncrese) ' Place our form as a child of Clock==> lParentOld = SetParent(Me.hwnd, TrayNotifyWnd) SetWindowPlacement Me.hwnd, wpClock End Sub Private Sub Form_Load() HijackTrayClock 100 Me.BackColor = &HC0C0FF Me.AutoRedraw = True Timer1.Interval = 1000 Timer2.Interval = 5 Me.Print Time End Sub Private Sub Timer1_Timer() Me.Cls Me.Print Time End Sub Private Sub Form_Click() Unload Me End Sub Private Sub Form_Unload(Cancel As Integer) ' Restore all ==> SetParent Me.hwnd, lParentOld SetWindowPlacement TrayNotifyWnd, wpTrayOld SetWindowPlacement TrayClockWClass, wpClockOld SetWindowPlacement ReBarWindow32, wpRebarOld End Sub Private Sub CopyUDT(wpSource As WINDOWPLACEMENT, wpDest As WINDOWPLACEMENT) wpSource.flags = wpDest.flags wpSource.Length = wpDest.Length ' wpSource.ptMaxPosition.x = wpDest.ptMaxPosition.x wpSource.ptMaxPosition.y = wpDest.ptMaxPosition.y ' wpSource.ptMinPosition.x = wpDest.ptMinPosition.x wpSource.ptMinPosition.y = wpDest.ptMinPosition.y ' wpSource.rcNormalPosition.Top = wpDest.rcNormalPosition.Top wpSource.rcNormalPosition.Bottom = wpDest.rcNormalPosition.Bottom wpSource.rcNormalPosition.Left = wpDest.rcNormalPosition.Left wpSource.rcNormalPosition.Right = wpDest.rcNormalPosition.Right ' wpSource.showCmd = wpDest.showCmd End Sub Private Function IsEqualUDT(wp1 As WINDOWPLACEMENT, wp2 As WINDOWPLACEMENT) As Boolean IsEqualUDT = (wp1.flags = wp2.flags) And _ (wp1.Length = wp2.Length) And _ (wp1.ptMaxPosition.x = wp2.ptMaxPosition.x) And _ (wp1.ptMaxPosition.y = wp2.ptMaxPosition.y) And _ (wp1.ptMinPosition.x = wp2.ptMinPosition.x) And _ (wp1.ptMinPosition.y = wp2.ptMinPosition.y) And _ (wp1.rcNormalPosition.Top = wp2.rcNormalPosition.Top) And _ (wp1.rcNormalPosition.Bottom = wp2.rcNormalPosition.Bottom) And _ (wp1.rcNormalPosition.Left = wp2.rcNormalPosition.Left) And _ (wp1.rcNormalPosition.Right = wp2.rcNormalPosition.Right) And _ (wp1.showCmd = wp2.showCmd) End Function Private Sub GetHwnd() ' Find the SystemTray and Clock windows ==> hShellTrayWnd = FindWindow("Shell_TrayWnd", vbNullString) TrayNotifyWnd = FindWindowEx(hShellTrayWnd, ByVal 0&, "TrayNotifyWnd", vbNullString) TrayClockWClass = FindWindowEx(TrayNotifyWnd, ByVal 0&, "TrayClockWClass", vbNullString) ReBarWindow32& = FindWindowEx(hShellTrayWnd, 0&, "ReBarWindow32", vbNullString) End Sub Private Sub ResizeClock(lWidthIncrese As Long) ' Resize the SystemTray ==> GetWindowPlacement TrayNotifyWnd, wpTray wpTray.rcNormalPosition.Left = wpTray.rcNormalPosition.Left - lWidthIncrese SetWindowPlacement TrayNotifyWnd, wpTray ' Resize the Clock ==> ' GetWindowPlacement TrayNotifyWnd, wpTray GetWindowPlacement TrayClockWClass, wpClock wpClock.rcNormalPosition.Right = wpClock.rcNormalPosition.Right + lWidthIncrese SetWindowPlacement TrayClockWClass, wpClock ' Resize QuickLaunch and RunningApplications toolbars ==> GetWindowPlacement ReBarWindow32, wpRebar wpRebar.rcNormalPosition.Right = wpRebar.rcNormalPosition.Right - lWidthIncrese SetWindowPlacement ReBarWindow32, wpRebar End Sub Private Sub SaveOriginalPlacement() ' Save current position of SystemTray and Clock ' We'll restore them when exiting ==> GetWindowPlacement TrayClockWClass, wpClockOld GetWindowPlacement TrayNotifyWnd, wpTrayOld GetWindowPlacement ReBarWindow32, wpRebarOld End Sub Private Sub Timer2_Timer() Dim wp1 As WINDOWPLACEMENT Dim wp2 As WINDOWPLACEMENT GetWindowPlacement TrayNotifyWnd, wp1 wpTray.rcNormalPosition.Bottom = wp1.rcNormalPosition.Bottom wpClock.rcNormalPosition.Bottom = wp1.rcNormalPosition.Bottom If Not IsEqualUDT(wp1, wpTray) Then SetWindowPlacement TrayNotifyWnd, wpTray SetWindowPlacement TrayClockWClass, wpClock End If SetWindowPlacement Me.hwnd, wpClock End Sub
Dear IFrank,
I am not abled to implement.The clock flicker.