1 Attachment(s)
[VB6] - Custom rendering window.
In Windows 7, there was a remarkable thing - indication of progress on the taskbar button. To use this feature on VB6 (and any other language) you need to create an object TaskBarList, get ITaskBarList3 interface and use its methods - SetProgressState and SetProgressValue. In my module, I added the ability to set the state of the progress bar on the taskbar, and duplicated this indicator on the form itself + added ability to use animated icons in the form header (also supported by the usual icons). From this example, you can learn how to draw the non-client area of the window, make buttons that are highlighted when hovering. The example uses double buffering, so everything works smoothly and without flicker. This module can be connected to any project with any forms.
Functions:
SetNCSkin - set new style window;
RemoveNCSkin - remove style from window;
SetIcon - set animated (or simple) icon to window;
PlayAnimation - enable playing icon animation;
StopAnimation - stop animation playing;
SetProgressState - set state of taskbar button;
GetProgressState - get state of taskbar button;
SetProgressValue - set value of progressbar in the taskbar button (0..1);
GetProgressValue - same, only get a value.
Example use:
Code:
Option Explicit
' Тестовая форма модуля пользовательской отрисовки окна
' © Кривоус Анатолий Анатольевич (The trick), 2014
Dim Value As Single
Private Sub cboIcon_Click()
Select Case cboIcon.ListIndex
Case 0: SetIcon Me, LoadResPicture("TRICKICON", vbResBitmap), 21
Case 1: SetIcon Me, LoadResPicture("WAITICON", vbResBitmap), 20
End Select
End Sub
Private Sub cmdDuplicate_Click()
Dim frm As frmTest
Set frm = New frmTest
frm.Show
End Sub
Private Sub cmdHideProgress_Click()
SetProgressState Me, TBPF_NOPROGRESS
End Sub
Private Sub cmdIcon_Click()
PlayAnimation Me, 32, False
End Sub
Private Sub cmdIconLoop_Click()
PlayAnimation Me, 32, True
End Sub
Private Sub cmdProgress_Click()
tmrTimer.Enabled = True
Value = 0
End Sub
Private Sub cmdShowProgress_Click()
If optState(0).Value Then SetProgressState Me, TBPF_NORMAL
If optState(1).Value Then SetProgressState Me, TBPF_PAUSED
If optState(2).Value Then SetProgressState Me, TBPF_ERROR
End Sub
Private Sub cmdStopAnimation_Click()
StopAnimation Me
End Sub
Private Sub cmdStopProgress_Click()
tmrTimer.Enabled = False
End Sub
Private Sub Form_Load()
SetNCSkin Me
cboIcon.ListIndex = 0
End Sub
Private Sub Form_Unload(Cancel As Integer)
RemoveNCSkin Me
End Sub
Private Sub optState_Click(Index As Integer)
Call cmdShowProgress_Click
End Sub
Private Sub tmrTimer_Timer()
Value = Value + 0.01
SetProgressValue Me, Value
End Sub
Re: [VB6] - Custom rendering window.
Thanks for sharing this. I'm considering different ways to display progress in my app and this looks interesting!
Re: [VB6] - Custom rendering window.
AAraya, thanks! This is worked project that uses that approach.
Re: [VB6] - Custom rendering window.
Thanks for the link to the working project - I'll definitely check that out too. Not only for the progress bar code but for the music generation portion. I'm a musician and have a side app I've been working with slowly over the years - I may be able to borrow some ideas from you in that area as well.
Re: [VB6] - Custom rendering window.
Problem getting it to work
There is a reference to test.tlb.
Test.tlb is not to find in the project folder.
So I think I can select the Taskbar.tlb.
It is checked in the references dialog.
When I click OK, then this comes up:
Microsoft Visual Basic - Error in loading DLL
What do I miss?
Thanks for a hint.
(Win10/64, IDE manifested)
Re: [VB6] - Custom rendering window.
Solved.
The tlb failed to create a reference also in a new, empty project.
I used the MIDL compiler to create a new tlb from the idl.
Interestingly it has another GUID than the original, only the very last number.
This new tlb loads fine, and with Custom rendering window as well.
Re: [VB6] - Custom rendering window.
Hi The Trick, I found that Form_Resize is not being executed.
I fixed changing WndProc with:
Code:
Case WM_SIZE
WndProc = OnSize(hwnd, wParam, lParam And &HFFFF&, (lParam \ &H10000) And &HFFFF&)
Call CallOldWndProc(hwnd, msg, wParam, lParam) ' <- Added line
Re: [VB6] - Custom rendering window.
Impossible reference to Taskbar.tlb
If I convert the idl also not working... Y use Win 10 32 Bits, is possible this code is for 64Bits Windows?
Re: [VB6] - Custom rendering window.
James Reynolds, i have updated the archive in the original post.
Re: [VB6] - Custom rendering window.
Very nice project...'
I'm scratching my head trying to understand this though... you frequently use GetMem4 ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34, stat
This is used like it's referring to the ButtonState... but why is it seemingly taking 2 bytes of empty padding space and only the first two bytes of ButtonState?
Code:
Private Type AnimIcon
Sequence As Long '12
NumOfFrame As Long '16
CurFrame As Long '20
State As Long '24
Interval As Long '28
Looped As Boolean '32
(padding, 2 bytes) '34
End Type
Private Type WndExtInfo
lpOldWndProc As Long 'Ptr + 0
ProgressValue As Single '4
ProgressState As TaskbarLib.TBPFLAG '8
Icon As AnimIcon
ButtonsState As Long '36
End Type
And SetExtInfo is using CopyMemory ByVal pt, wi, Len(wi); when Len and LenB don't match; and
GetMem4 ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34, stat
btnidx = GetBtnIndex(pos)
stat = stat Or (&H100& * (btnidx + 1))
GetMem4 stat, ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34
Given your skills I'm extremely hesitant to assume this is a bug; so is there another reason why the 2 bytes padding + 2 bytes ButtonsState, instead of +36 and just ButtonsState? I suppose it doesn't strictly matter as long as its consistent, but who knows when someone else will get confused and go looking :wave:
Re: [VB6] - Custom rendering window.
Quote:
Originally Posted by
fafalone
Very nice project...'
I'm scratching my head trying to understand this though... you frequently use
GetMem4 ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34, stat
This is used like it's referring to the ButtonState... but why is it seemingly taking 2 bytes of empty padding space and only the first two bytes of ButtonState?
Code:
Private Type AnimIcon
Sequence As Long '12
NumOfFrame As Long '16
CurFrame As Long '20
State As Long '24
Interval As Long '28
Looped As Boolean '32
(padding, 2 bytes) '34
End Type
Private Type WndExtInfo
lpOldWndProc As Long 'Ptr + 0
ProgressValue As Single '4
ProgressState As TaskbarLib.TBPFLAG '8
Icon As AnimIcon
ButtonsState As Long '36
End Type
And SetExtInfo is using
CopyMemory ByVal pt, wi, Len(wi); when Len and LenB don't match; and
GetMem4 ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34, stat
btnidx = GetBtnIndex(pos)
stat = stat Or (&H100& * (btnidx + 1))
GetMem4 stat, ByVal GetWindowLong(hwnd, GWL_USERDATA) + 34
Given your skills I'm extremely hesitant to assume this is a bug; so is there another reason why the 2 bytes padding + 2 bytes ButtonsState, instead of +36 and just ButtonsState? I suppose it doesn't strictly matter as long as its consistent, but who knows when someone else will get confused and go looking :wave:
Yes this is the bug. Thank you for testing! When i used GetWindowLong(hwnd, GWL_USERDATA) + 34 i just read/write to the padding and part of ButtonsState member. Because of i don't access to ButtonsState directly using VB6 code so this bug doesn't affect to program behavior. Thank you for the test, you are very attentive :)
Re: [VB6] - Custom rendering window.
Hi, The trick! Am I understand right that I can't use the Menu editor in this project? Or is there any workaround?
Re: [VB6] - Custom rendering window.
Quote:
Originally Posted by
Nouyana
Hi, The trick! Am I understand right that I can't use the Menu editor in this project? Or is there any workaround?
It need to do additional steps to draw a menu because the menu is non-client area.
Re: [VB6] - Custom rendering window.
Quote:
Originally Posted by
The trick
It need to do additional steps to draw a menu because the menu is non-client area.
It would be great! Especially if it becomes visual styled, not like in the days of Win98.