VB6 sidebar app - vb6

All.
I'm attempting to develop a 'sidebar' application with vb6, which I want to behave like windows Vista's gadget sidebar or Google Desktop sidebar, in the respect that other windows could not maximize over it.
I'm aware that chances of this happening are probably very little, but I'm asking just in case.
Currently, I've got a form that has multiple controls, and runs a function on load which makes itself the exact height of the screen, minus the taskbar, and it's 'left' location is set by a timer to be 'screen.width - me.width', so it will start at full height on the far right of the screen, and cannot be moved. Code for the height is as follows, if it is necessary.
Declare Function GetUserNameA Lib "advapi32.dll" (ByVal lpBuffer As String, nSize As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Declare Function SetLayeredWindowAttributes Lib "user32" ( _
ByVal hwnd As Long, _
ByVal crKey As Long, _
ByVal bAlpha As Byte, _
ByVal dwFlags As Long) As Long
Public Const GWL_STYLE = (-16)
Public Const GWL_EXSTYLE = (-20)
Public Const WS_EX_LAYERED = &H80000
Public Const LWA_COLORKEY = &H1
Public Const LWA_ALPHA = &H2
Private Const ABM_GETTASKBARPOS = &H5
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type APPBARDATA
cbSize As Long
hwnd As Long
uCallbackMessage As Long
uEdge As Long
rc As RECT
lParam As Long
End Type
Private Declare Function SHAppBarMessage Lib "shell32.dll" (ByVal dwMessage As Long, pData As APPBARDATA) As Long
Function Fixheight()
Dim ABD As APPBARDATA
SHAppBarMessage ABM_GETTASKBARPOS, ABD
Form1.Height = Screen.Height - ((ABD.rc.Bottom - ABD.rc.Top) * 12)
If Form1.Height <= 600 Then
Form1.Height = Screen.Height
End If
End Function
To be clear, I do not want an 'always on top' function. I already have that, and it's driving me insane, as the form has to me closed or minimized in order to maximize, minimize of close another program (i.e. chrome, word, etc) behind it. This form must instead not allow other programs to maximize over it, so that if for example, the user maximized Chrome, chrome would maximize minus form1.width.
I doubt that this is possible because as far as I'm concerned, that would mean taking control of chrome, and essentially making it's maximize function as
me.height = screen.height - ((ABD.rc.Bottom - ABD.rc.Top) * 12)
me.width = screen.width - form1.width
which isn't possible.
Anyway, hopefully someone out there can help. As I said, I seriously doubt the possibility of having this work, but if so, all the better.
Thanks in advance!

Thanks to Ken White, I googled SHAppBarMessage and found the following website, offering a downloadable source with the very feature I needed. I just have to implement it now!!
Very glad I asked! Thank you!
Edit: Found this spanish website, which while needed some help from Google Translate, is more suited to my needs. Just need to figure out how to make it work on the Right Hand Side! Thanks again!

Related

How to find correct values for HWND window handles?

WinRestore,% hwnd([1])
i have found in many programming language the use of hwnd. after searching on google it comes out to be handle. I didnt got more information on this. how programmer knows the value to put in, eg.
Const LB_GETTEXTLEN = &H18A
Const LB_GETTEXT = &H189
Const LB_GETCOUNT = &H18B
&h18a how he known, how will he use this?
this is the example program
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Const LB_GETTEXTLEN = &H18A
Const LB_GETTEXT = &H189
Const LB_GETCOUNT = &H18B
Private Function GetListItems(ByVal hList As Long) As Variant
Dim i As Long, nCount As Long, lItemLength As Long
Dim sItem() As String
nCount = SendMessage(hList, LB_GETCOUNT, 0, ByVal 0&)
For i = 0 To nCount - 1
lItemLength = SendMessage(hList, LB_GETTEXTLEN, i, ByVal 0&)
ReDim Preserve sItem(i)
sItem(i) = String(lItemLength, 0)
Call SendMessage(hList, LB_GETTEXT, i, ByVal sItem(i))
Next i
GetListItems = sItem
End Function
there are many such examples in all different languages but concept will be the same. so i want to learn it. what does it mean and how to use it.
another example from ahk
Gui,2:+hwndhwnd
hwnd(2,hwnd)
Those are all window messages that you can find information about on the MSDN Documentation by googling them. See below links:
LB_GETTEXTLEN
LB_GETTEXT
LB_GETCOUNT
You can find them and other related messages by checking the documentation for the native List Box control.
As for the numbers they're hexadecimal numbers which are (usually) mentioned in the documentation. But since these aren't you'll have to google them and check other websites/forums, or find their values on your own by experimenting with them in C or C++ .
In VB hexadecimal numbers are represented by prepending the number with &H, whereas in C, C++, C# or alike they're prepended with 0x.
In a forms editor each window/control has a hwnd property. For windows not created by your forms package you use the API calls FindWindow (easiest but not reliable) or EnumWindows. Also GetForegroundWindow and GetDesktopWindow.
To find out the value of constants you download the C header files as part of the Windows SDK https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk. It also has the documentation for all these API calls. This is online documentation listing all the windows' functions https://msdn.microsoft.com/en-us/library/windows/desktop/ms633505(v=vs.85).aspx.

MS PowerPoint: how to convert a shape's position and size into screen coordinates?

I wrote me a little VBA Macro for PowerPoint (2010) that opens a popup with explanations when hovering over some Shape. This works fine. Alas, there is no event that is triggered when leaving the area again and so I now want to extend the code such that it monitors the area of the popup and when the pointer leaves that area it removes the popup again.
But now I ran into some stupid problem: the coordinates of the Shape (.Left, .Top, .Width, and .Height) are given in some "document units" (don't know exactly what unit this is in). The pointer coordinates, however, are obviously in screen pixels. To be able to reasonably compare the two to calculate whether the pointer is inside or outside I need to first convert the Shape's dimensions into screen pixels.
I googled around a lot, but while I found several at first promising code snippets, none of these worked (as most were for Excel and PowerPoint obviously has a different document model).
Could some kind soul give me a hint or some reference how to convert a Shape's dimension into screen pixels (i.e. taking scaling, window position, zoom-factor etc. into account).
M.
In case anyone's interested - here is my solution after LOTS of further googling:
Type POINTAPI
x As Long
y As Long
End Type
Type Rectangle
topLeft As POINTAPI
bottomRight As POINTAPI
End Type
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long, ByVal nIndex As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC As Long) As Long
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Function TransformShape(osh As Shape) As Rectangle
Dim zoomFactor As Double
zoomFactor = ActivePresentation.SlideShowWindow.View.zoom / 100
Dim hndDC&
hndDC = GetDC(0)
Dim deviceCapsX As Double
deviceCapsX = GetDeviceCaps(hndDC, 88) / 72 ' pixels per pt horizontal (1 pt = 1/72')
Dim deviceCapsY As Double
deviceCapsY = GetDeviceCaps(hndDC, 90) / 72 ' pixels per pt vertical (1 pt = 1/72')
With TransformShape
' calculate:
.topLeft.x = osh.Left * deviceCapsX * zoomFactor
.topLeft.y = osh.Top * deviceCapsY * zoomFactor
.bottomRight.x = (osh.Left + osh.width) * deviceCapsX * zoomFactor
.bottomRight.y = (osh.Top + osh.height) * deviceCapsY * zoomFactor
' translate:
Dim lngStatus As Long
lngStatus = ClientToScreen(hndDC, .topLeft)
lngStatus = ClientToScreen(hndDC, .bottomRight)
End With
ReleaseDC 0, hndDC
End Function
...
Dim shapeAsRect As Rectangle
shapeAsRect = TransformShape(someSape)
Dim pointerPos As POINTAPI
Dim lngStatus As Long
lngStatus = GetCursorPos(pointerPos)
If ((pointerPos.x <= shapeAsRect.topLeft.x) Or (pointerPos.x >= shapeAsRect.bottomRight.x) Or _
(pointerPos.y <= shapeAsRect.topLeft.y) Or (pointerPos.y >= shapeAsRect.bottomRight.y)) Then
' outside:
...
Else ' inside
...
End If
...
the coordinates of the Shape (.Left, .Top, .Width, and .Height) are given in some "document units" (don't know exactly what unit this is in).
Points. 72 points to the inch.
Sub TryThis()
Dim osh As Shape
Set osh = ActiveWindow.Selection.ShapeRange(1)
With ActiveWindow
Debug.Print .PointsToScreenPixelsX(.Left)
Debug.Print .PointsToScreenPixelsY(.Top)
End With
End Sub

Shutdown computer at specific time programmatically

I need an application with a feature that user should be able to set time of computer automatic shutdown (closing all opened applications) in visual basic 6.
I just need to know is this doable? if yes, what specific topics should I search? honestly, never did system programs in vb just m a db programmer that too of a primitive nature. (so gurus, thanks for understanding ;)
Option Explicit
Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
Public Const EWX_FORCE = 4
Public Const EWX_LOGOFF = 0
Public Const EWX_REBOOT = 2
Public Const EWX_SHUTDOWN = 1
Public Sub Main()
Dim Res As Long
MsgBox ("Your System Will Now Shutdown")
Res = ExitWindowsEx(EWX_SHUTDOWN, 0)
End Sub
source
this does the job as required by you.

Set global hotkey with Windows modifier

I want to set up a global hotkey* in VB6 that listens to the keyboard shortcut Win + O.
I have found heaps of messy examples, but nothing which involves the Windows key.
What's the ideal way to setup hotkeys and how does one include the Windows key as a modifier?
* I'm after a global shortcut. That means I don't have to have the application in focus for it to work.
RegisterHotKey in the Windows API will allow you to register a global hot key. You will also need to use GlobalAddAtom to obtain a unique hot key identifier. See this link for details.
Private Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Private Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal lpString As String) As Integer
Private Const WM_HOTKEY As Long = &H312
Private Const MOD_WIN As Long = &H8
m_lHotkey = GlobalAddAtom("MyHotkey")
Call RegisterHotKey(Me.hwnd, m_lHotkey, MOD_WIN, vbKeyO)
Then you just need to listen for the WM_HOTKEY message on your window.

CheckTokenMembership in VB6

I'm having a hard time converting this C++ code to VB6 code. I've search the net and haven't found anything. PInvoke.net only has reference to VB.NET code. Here's the code from MSDN:
BOOL IsUserAdmin(VOID)
/*++
Routine Description: This routine returns TRUE if the caller's
process is a member of the Administrators local group. Caller is NOT
expected to be impersonating anyone and is expected to be able to
open its own process and process token.
Arguments: None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group. --
*/
{
BOOL b;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup;
b = AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdministratorsGroup);
if(b)
{
if (!CheckTokenMembership( NULL, AdministratorsGroup, &b))
{
b = FALSE;
}
FreeSid(AdministratorsGroup);
}
return(b);
}
It would be great if somebody can help out in converting this to VB6 code.
Thanks!
EDIT:
I was originally going to use that function but MSDN says:
This function is a wrapper for CheckTokenMembership. It is recommended to call that function directly to determine Administrator group status rather than calling IsUserAnAdmin.
Try this
Option Explicit
Private Const SECURITY_BUILTIN_DOMAIN_RID As Long = &H20
Private Const DOMAIN_ALIAS_RID_ADMINS As Long = &H220
Private Declare Function AllocateAndInitializeSid Lib "advapi32.dll" (pIdentifierAuthority As Any, ByVal nSubAuthorityCount As Byte, ByVal nSubAuthority0 As Long, ByVal nSubAuthority1 As Long, ByVal nSubAuthority2 As Long, ByVal nSubAuthority3 As Long, ByVal nSubAuthority4 As Long, ByVal nSubAuthority5 As Long, ByVal nSubAuthority6 As Long, ByVal nSubAuthority7 As Long, lpPSid As Long) As Long
Private Declare Sub FreeSid Lib "advapi32.dll" (ByVal pSid As Long)
Private Declare Function CheckTokenMembership Lib "advapi32.dll" (ByVal hToken As Long, ByVal pSidToCheck As Long, pbIsMember As Long) As Long
Private Type SID_IDENTIFIER_AUTHORITY
Value(0 To 5) As Byte
End Type
Private Function pvIsAdmin() As Boolean
Dim uAuthNt As SID_IDENTIFIER_AUTHORITY
Dim pSidAdmins As Long
Dim lResult As Long
uAuthNt.Value(5) = 5
If AllocateAndInitializeSid(uAuthNt, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, pSidAdmins) <> 0 Then
If CheckTokenMembership(0, pSidAdmins, lResult) <> 0 Then
pvIsAdmin = (lResult <> 0)
End If
Call FreeSid(pSidAdmins)
End If
End Function
You've posted the MSDN sample code for CheckTokenMembership - it uses CheckTokenMembership to determine whether the user is an administrator.
In VB6 it's easier to use IsUserAnAdmin, which is a wrapper for CheckTokenMembership. The MSDN docs do say IsUserAnAdmin is deprecated, but it's so much easier to call than CheckTokenMembership.
Private Declare Function IsUserAnAdmin Lib "Shell32" Alias "#680" () As Integer
If IsUserAnAdmin() = 0 Then
MsgBox "Not admin"
Else
MsgBox "Admin"
End If
Unless there is a reason to convert the code, use the API
Private Declare Function IsUserAdmin Lib "Shell32" Alias "#680" () As Boolean
Private Sub Form_Load()
If IsUserAdmin Then MsgBox "User is Admin"
End Sub

Resources