EM_SETCUEBANNER sendmessage vb.net usercontrol not working - user-controls

If I use the code shown below on a vb.net winform the cue banner / watermark appears and behaves as expected (Win7 Pro 32bit VS2008 & 64bit VS2010). However when using the same style of code in a vb.net usercontrol the watermark is not displayed. Anyone got any clues?
Some hours later... This is looking like PEBKAC. Works in a test app. with user controls. Both those created at design time and those loaded at run-time, still doesn't work in the main app. though. Still puzzled. Still looking for a clue.
' Call from form / usercontrol load event handler.
Userhint.WatermarkSet(textbox1, "Some arbitrary text.")
' Noddy library class.
Friend Class Userhint
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>_
Private Shared Function SendMessage(ByVal hWnd As HandleRef, _
ByVal Msg As UInteger, _
ByVal wParam As IntPtr, _
ByVal lParam As String) As IntPtr
End Function
Public Shared Sub WatermarkSet(ByVal ctl As Control, _
byval hintText as string)
const EM_SETCUEBANNER as int32 = &h1501
dim retainOnFocus As IntPtr = new IntPtr(1)
SendMessage(New HandleRef(ctl, ctl.Handle), _
EM_SETCUEBANNER, _
retainOnFocus, _
hintText)
End sub
End Class

Not so much PEBKAC as yet another instance of M$ not documenting things as well as they might.
The short answer is to call Application.EnableVisualStyles() before the Run method.
Application.EnableVisualStyles()
Application.Run()
See questions/7518894/sendmessage-doesnt-work-in-one-project on this site for more info.

Related

how to get inner text of message from web page?

I'm using below code to intract with the POP-Up/Message from webpage.
hWND = FindWindow(vbNullString, "Message from webpage")
hWND <> 0 Then childHWND = FindWindowEx(hWND, ByVal 0&, "Button", "OK")
If childHWND <> 0 Then SendMessage childHWND, BM_CLICK, 0, 0
The POP up displays a value, such as "CGPA : 10", I wish to save that text ("CGPA : 10") in a variable.
I'm coding in VBA.
Might suggest getting something either like Selnium or Playwright that will drive and test web based application. The main problem i'm seeing you are doing FindwindowEx and the native Win32 api's are for Win32 native apps and not web applications as Selenium and Playwright are. Either of them would be the right way to go.

Set Focus on an Excel User Form Using VBA

I got my project 95% done but a small issue remains. My code, run from a user form, opens a PDF document with its first line, identifies its window in the second and moves and resizes that window in the third.
ActiveWorkbook.FollowHyperlink Mail(0) & Mail(Me.Tag)
Wnd = FindWindow(vbNullString, AcrobatWindowID(Mail(Me.Tag)))
SetWindowPos Wnd, HWND_TOP, 1950, 10, 1100, 1300, SWP_NOACTIVATE
At the end of this operation the user form is dimmed out. The focus seems to remain with the PDF. That doesn't really matter because the form is fully developed and I can click on it or the PDF to activate either, just the way I wanted.
Nevertheless I tried to give the focus to the form and then to a particular control. I succeeded in finding the Excel window but failed to set the focus on the form, not to mention the control. In fact, I don't know how to check if I succeeded in setting the focus on the Excel window. I used this code in my attempt of whose syntax I'm not sure.
Public Const SWP_NOMOVE = &H2 ' ignore cx and cy
Public Const SWP_NOSIZE = &H1 ' ignore X and Y
SetWindowPos Wnd, HWND_TOP, 0, 0, 0, 0, (SWP_NOMOVE + SWP_NOSIZE)
Anyway, the form remains dimmed out. Does anyone have advice for me?
In order to obtain the form handler, you should proceed in this way:
Use API GetActiveWindow and create a Private variable on top of the form code module (in the declarations area):
Option Explicit
Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
Private frmHwnd as LongPtr
Insert the next code line in the UserForm_Initialize event:
frmHwnd = GetActiveWindow

Sub works differently through button on the worksheet

So I've spent the evening trying to design snake in VBA. Great stuff. It seemed to be working fine whenever I ran the Main Sub from the VBA window (by clicking the play button in the top ribbon), however when I added a button on the worksheet for the same sub, it runs with no errors but the controls don't behave in the same way. Originally each time you press an arrow you just change direction, however when running the macro through a button you can keep holding the arrow in the direction you're going and it speeds up the snake, so the cell select behaves as it normally would in Excel, rather than as required in snake. This defeats the purpose of the game as the rest of the snake can't catch up with the head and creates gaps within allowing the user to just jump through it.
I'm using GetAsyncKeyState to read key presses:
#If VBA7 Then
Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Long) As Integer
#Else
Private Declare Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Long) As Integer
#End If
Private Const VK_LEFT = &H25 'LEFT ARROW key
Private Const VK_UP = &H26 'UP ARROW key
Private Const VK_RIGHT = &H27 'RIGHT ARROW key
Private Const VK_DOWN = &H28 'DOWN ARROW key
And then calling this with If Statements:
' Key press handling
WasteTime (speed)
If GetAsyncKeyState(VK_DOWN) Then
PressDown
ElseIf GetAsyncKeyState(VK_UP) Then
PressUp
ElseIf GetAsyncKeyState(VK_LEFT) Then
PressLeft
ElseIf GetAsyncKeyState(VK_RIGHT) Then
PressRight
End If
' Offset by key direction or default
ActiveCell.Offset(cellrow, cellcol).Select
For reference, this is all that each key function does:
Function PressUp()
cellrow = -1
cellcol = 0
End Function
Any help would be greatly appreciated. I suspect this has something to do with me declaring the GetAsyncKeyState function in the General Declarations section, but as I've never done this before, can't quite work out what I'm doing wrong. Thanks :)

Why MouseMove event is continuously fired on Modeless form even with the stationary mouse?

I have an Excel form in which I use controls' mouse move event for simulating hovering effect.
There's no problem when the form is showed modal.
When I show the form modeless, even with the stationary mouse, the mousemove event of every control is continuously fired (if the mouse is over that control). The CPU usage grows up to 26-30%.
Nothing changes if the mouse move event has no code inside.
If I comment the entire events this strange behavior disappears.
It seems that the mere existence of the mouseMove event it's enough to create the problem.
I've searched a lot, but it seems I'm the only one having this problem.
I can share the workbook if anyone wants to see it.
I have a relatively simple solution that should handle the CPU usage problem, this doesn't do anything against the event triggering while the mouse is stationary though. The idea is to use the sleep function provided by the windows API to decrease the frequency of the events activation.
So first you need to get the function:
#If VBA7 Then
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
Public Declare Sub Sleep Lib "kernel32" (ByVal lngMilliSeconds As Long)
#End If
and then inside your userform:
Private Sub Label1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
sleep 1 '1 should be the time in milliseconds that the code will wait,
'in practice it waits 15ms (see edit below)
'insert the rest of your code here
End Sub
The sleep 1 will make the code wait for one millisecond before resuming execution. Edit: in practice it will make the code wait for 15 milliseconds, see #GSergs comment to this answer.
This is usually enough to get rid of the cpu usage problem. If you don't need the event to trigger 65 times a second you can change the triggering frequency by waiting longer, for example with sleep 30.
If you only need the event to activate once every time the mouse goes from "not over the control" to "over the control" a solution is to use an activation flag:
Inside the Userforms Module:
Dim ControlActive As Boolean
Private Sub Label1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If Not ControlActive Then
ControlActive = True
'insert the rest of your code here
End If
End Sub
Private Sub Userform_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If ControlActive Then
ControlActive = False
End If
End Sub

Excel VBA TAPI to blind transfer extension

I have dialed a number using tapirequestmakecall function using Excel VBA.
https://msdn.microsoft.com/en-us/library/ms737210(v=vs.85).aspx
Declare Function tapiRequestMakeCall Lib "tapi32.dll" _
(ByVal stNumber As String, ByVal stDummy1 As String, _
ByVal stDummy2 As String, ByVal stDummy3 As String) As Long
Sub DialNumber(Number As String)
Dim lngStatus As Long
lngStatus = tapiRequestMakeCall(Number, "", "", "")
If lngStatus < 0 Then
MsgBox "Failed to dial number " & Number, vbExclamation
End If
End Sub
I have to transfer the call to extension like 100 after call is connected.
How to do this? Am using TAPI 2.2. Any help would be highly appreciated..
As far as I'm aware, this is not possible. The built-in office TAPI integration is only intended for making an outgoing call with a "1st party"-TAPI driver (a subset of drivers intended for single extension use). Office also limits the access to the API (for "easy" use), hence you do not have access to the normal output of a dial action (= the handle of the created call, to perform further actions).
I would suggest you do not use the built-in office methods but build directly on TAPI (tapi32.dll) itself. Unfortunately, that is a considerably more difficult job.

Resources