I have attempted to use an autoit object WinGetPos to handle a popup within a thread in a vb project, I would like WinGetPos function to return the x and y coordiantes of the specified popup and have used the below code, having first imported the AutoItX3.PowerShell.dll reference to my project. I am unable to generate any array could anyone suggest where I might be going wrong?
Imports AutoIt
Imports AutoItX3Lib
Private Declare Auto Function WinGetPos Lib "AutoItX3.PowerShell.dll" (ByVal mywindowtitle As String) As Array
Public Sub Main()
Dim PopUpThread As Thread = New Thread(AddressOf PopUpHandler)
With PopUpThread 'thread is looking for PopUp and press OK
.IsBackground = True
.Start()
End With
End Sub
Private Sub PopUpHandler()
Dim Ret As Integer
Dim myarray As Array
Do
Ret = FindWindow(vbNullString, "Choose File to Upload")
If Ret <> 0 Then
myarray = WinGetPos("Choose File to Upload")
MsgBox(UBound(myarray))
End If
Loop
End Sub
AutoItX is a well known and documented Programm. So why don't just look into the help file. There you will find how to use and WinGetPosX, WinGetPosY, WinGetPosHeight and WinGetPosWidth, but no WinGetPos. That may be the reason for your problem.
Related
Thanks for reading.
I have built a VB6 DLL (VB_InterFace just for a name) that talks to a C# DLL (C#_Driver just for a name) that talks to a Bluetooth Device.
The Demo VB6 test app (VB_Demo just for a name) I created as stage one works fine, does what it is supposed to. It calls the VB_Interface and Opens and Closes the BTDevice. Additional functions also work fine.
However on placing the operational code from VB_Interface into another DLL that is the live operations DLL, Open works fine, but Close is throwing an error. "Variable not defined" when returning from the C#_Driver.
I just can't see why, the code is the same, the process is only marginally different. By this I mean ;
In the VB_Demo I have two buttons "Open" "Close" and when I click on these I get the feedback that I expect from the BTDevice.
Private Sub btnOpenPort_Click()
'MsgBox steps(0)
ReDim steps(5)
Dim rc As HF4000_ResultCodes
'rc = driver.OpenSerial(cmbPorts.Text)
If driver.OpenSerial(cmbPorts.Text) = True Then
Private Sub btnClosePort_Click()
Dim rc As HF4000_ResultCodes
If driver.CloseSerial("COM4") = True Then
However in the live DLL it just executes the same functions internally without being initiated by a button click.
' See IScanDevice documentation.
' #see IScanDevice#OpenDevice
Private Function IScanDevice_OpenDevice() As Scanning.Scan_ResultCodes
(truncated slightly)
50 If driver.OpenSerial("COM4") = True Then
rc = READY
MsgBox "Connected to the device successfully."
' See IScanDevice documentation.
' #see IScanDevice#CloseDevice
Private Function IScanDevice_CloseDevice() As Scanning.Scan_ResultCodes
(truncated slightly)
50 If driver.CloseSerial("COM4") = True Then
60 rc = READY
70 IScanDevice_CloseDevice = Scan_Success
clsDriver.cls
Public Event OnStateChanged(newState As String)
Public Event OnDataUpdated()
Dim WithEvents CSharpInteropServiceEvents As CSharpInteropService.LibraryInvoke
Dim load As New LibraryInvoke
Private Sub Class_Initialize()
Set CSharpInteropServiceEvents = load
End Sub
Private Sub CSharpInteropServiceEvents_MessageEvent(ByVal newState As String)
If newState = "OpenForm1" Then
' FormDummy2.Show ' Not required
End If
If State <> newState Then
State = newState
RaiseEvent OnStateChanged(State)
GetDriverData
End If
End Sub
Private Function BluetoothTestInvoke(load, functionName, param)
BluetoothTestInvoke = load.GenericInvoke("BluetoothTest.dll", "BluetoothTest.Class1", functionName, param)
End Function
Function OpenSerial(portNumber) ' "COM4"
Dim param(0) As Variant
Dim retorno As Variant
param(0) = portNumber
retorno = BluetoothTestInvoke(load, "OpenSerial", param)
OpenSerial = retorno(0) <<<<<<< Works fine returns TRUE
End Function
Function CloseSerial(portNumber) ' "COM4"
Dim param(0) As Variant
Dim retorno As Variant
param(0) = portNumber
retorno = BluetoothTestInvoke(load, "CloseSerial", param)
CloseSerial = retorno(0) <<<<<<<<< "Error Subscript Out of Range"
End Function
What I have discovered is this - and I guess this is the reason why the Close is not working. The question is why is this situation occurring ...
When driver.OpenSerial executes, it hits > Function OpenSerial
Within Function OpenSerial it executes BluetoothTestInvoke where "load" is "CSharpInteropService.LibraryInvoke"
From there it moves to - Sub CSharpInteropServiceEvents_MessageEvent
.. and everything is fine.
However when I then execute driver.CloseSerial after that, it hits > Function CloseSerial
Within Function OpenSerial it executes BluetoothTestInvoke where "load" is "CSharpInteropService.LibraryInvoke"
Now here it "should" move to - Sub CSharpInteropServiceEvents_MessageEvent
However No, it just drops to the next line which is CloseSerial = retorno(0)
and this is where I get the "Subscript out of range" error for retorno(0)
For some reason in the CloseSerial it is not invoking "load"
BluetoothTestInvoke(load, "CloseSerial", param)
Thoughts and suggestions much appreciated.
UPDATE
Quite right, one should never assume anything.
On the tips I started digging deeper into the C# Library. It turns out the "param" value that is the Bluetooth port is passed into the CloseSerial call, and from there is is passed around within the external C# library dll. At one stage it is reset so the port number that should be handled is lost, thus it doesn't close but specifically the "expected" data was not returned to the calling app.
param(0) = portNumber
retorno = BluetoothTestInvoke(load, "CloseSerial", param) << param was being reset in the external library.
In Visual basic 6, clipboard has various formats. To retrieve HTML data from the clipboard, this works great: https://support.microsoft.com/en-us/kb/274326
Now my question is, how can I get HTML information from dragged data and not the clipboard?
for example,
I'd like to have a multi-line textbox, that when I drag content from a webpage - into the textbox - the textbox will show the HTML retrieved from the OLE Dragging information, and not as vbCFtext.
I'v tried using the same technique as in the link above but instead of GetClipboardData - use Data.GetData(RegisterClipboardFormat("HTML Format")) [which is coming from Picture1_OLEDragDrop(...]
but I get an over flow error.
I have searched all over the web for a solution. anybody out there?
Edited: The above was answered, Thanks!
Adding:
Thank you very much! What would be the right way now to reverse that? meaning, to drag from a text box (that contains HTML) - and set it for dragging in HTML mode?
when I simply use this:
Private Sub Text1_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
'Data.SetData StrConv(Text1.Text, vbFromUnicode), (CF_HTML)
Data.SetData Text1.Text, (CF_HTML)
End Sub
I get an error:
"Non-intrinsic OLE drag and drop formats used with SetData require Byte array data. GetData may return more bytes than were given to SetData (Error 675)"
What would be the accurate way to send back the data?
and note that in could have Unicode characters.
will I have to use memory copy and others to get this to work? I'l appreciate your help very much!
Your problem is that RegisterClipboardFormat returns a Long (actually a uint), but clipboard formats are ushort (unsigned integer) values. Since we have no such type in VB6, our DataObject types expect Integer values. Thus we have to play a few more games:
Option Explicit
Private Declare Function RegisterClipboardFormat Lib "user32" _
Alias "RegisterClipboardFormatW" ( _
ByVal lpString As Long) As Long
Private CF_HTML As Integer
Private Sub Form_Initialize()
Dim Temp As Long
Temp = RegisterClipboardFormat(StrPtr("HTML Format"))
CF_HTML = CInt(Temp And &H7FFF&) Or IIf(Temp And &H8000&, &H8000, 0)
End Sub
Private Sub Text1_OLEDragDrop( _
Data As DataObject, _
Effect As Long, _
Button As Integer, _
Shift As Integer, _
X As Single, _
Y As Single)
If Effect And vbDropEffectCopy Then
Text1.Text = StrConv(Data.GetData(CF_HTML), vbUnicode)
End If
End Sub
Private Sub Text1_OLEDragOver( _
Data As DataObject, _
Effect As Long, _
Button As Integer, _
Shift As Integer, _
X As Single, _
Y As Single, _
State As Integer)
If Data.GetFormat(CF_HTML) Then
Effect = vbDropEffectCopy
Else
Effect = vbDropEffectNone
End If
End Sub
I am using the functions below.In the first one i have parsed the node of xml and its value using MSXML. similar func fr other xml.i want to use two nodevalues and highlight it.i tried something.but i am getting error in the line highlighted(**) as 'Object Required'.your quick reply will help me more.
Public Sub DisplayNode1(ByRef Nodes1 As MSXML2.IXMLDOMNodeList, _
ByVal Indent1 As Integer)
some lines
RichTextBox2.Text = Space$(Indent) & xNode1.ParentNode.nodeName & _
":" & xNode1.NodeValue
difference
some lines
Public Sub difference()
Dim a As IXMLDOMText
Dim b As IXMLDOMText
a.NodeValue = xNode.innertext 'i get erroe in line
b.NodeValue = xNode1.innertext
If StrComp(a, b) > 0 Then
a = vbRed
b = vbRed
End If
please help me soon.
There is a lot that is potentially wrong with this.
xnode isn't declared anywhere in your code sample
Neither a, b, or xnode are explicitly set anywhere in your code sample
Unless xnode is a form/module/global level variable then it will be out of scope in the Difference procedure
It's not shown but I'm guessing that you don't have Option Explicit set in your code or by default
You'll need to address these points first before you can get anywhere with this code.
Is it possible in VBScript to determine the name of the function currently executing?
In .NET, you could do:
MethodBase method = MethodBase.GetCurrentMethod();
Console.WriteLine(method.Name);
In the past, I build a callstack viewer to see the performance of each function that is called. This needs one extra line of VBS code per function/sub and some overhead during runtime of course because of the extra code.
bottom - up:
Function DoSomething(a, b, c)
dim registerFunctionObj : Set registerFunctionObj = [new RegisterFunction]("DoSomething")
' other code
End Function
Whenever the function is called, it creates a new instance of the RegisterFunction object. When the function exits, the registerFunctionObj variable goes out of scope automatically, calling the Class_Terminate sub of the instance.
[new RegisterFunction] is just a function that return a registerFunction instance:
Function [new RegisterFunction](funcName)
Set [new RegisterFunction] = new cls_RegisterFunction
[new RegisterFunction].FunctionName = funcName
Set [new RegisterFunction].CallStackViewer = CallStackViewer
End function
Class cls_RegisterFunction
Private functionName_, startTime_, callStackViewer_, endTime_
Private Sub Class_Initialize
startTime_ = now
callStackViewer_.LogInitialize me
End Sub
Public Property Let FunctionName(fName)
functionName_ = fName
End Property
Public Property Set CallStackViewer(byRef csv)
Set callStackViewer_ = csv
End Property
Private Sub Class_Terminate
endTime_ = now
callStackViewer_.LogTerminate me
End Sub
End Class
The CallStackViewer instance is a singleton instance of the a CallStackViewer class, but you can make it a part of your project, so you retrieve it through you global project class:
Private PRIV_callStackViewer
Public Function CallStackViewer()
If not IsObject(PRIV_callStackViewer) Then
Set PRIV_callStackViewer = new cls_CallStackViewer
End If
Set CallStackViewer = PRIV_callStackViewer
End Function
Class cls_CallStackViewer
Public Sub Class_Initialize
' Here you can retrieve all function libraries (as text file) extract the
' function name, the file they are in and the linenumber
' Put them in a dictionary or a custom object
End Sub
Public Sub LogInitialize(byref registerFunction)
' Here you can push the function on a stack (use a standard dotnet list>stack for it),
' log the starttime to a log object or handle custom breakpoints
End Sub
Public Sub LogTerminate(byref registerFunction)
' Here you can pop the function from a stack, log the endtime to a log
' object or handle custom breakpoints
End Sub
End Class
Disclaimer: The code in here is pure demo code created on the fly. It lacks functionality and is only here to explain the concept. It could contain errors and is not complete.
The only thing you need is one line of code per function and your own imagination to expand it.
No, but you can easily implement it
dim module_name
sub sub1
module_name = "sub1"
wscript.echo "i'm " & module_name
'do something
end sub
function function1
module_name = "function1"
wscript.echo "i'm " & module_name
function1 = "something"
end function
In case of recursion you could also remember the level you'r in so that you can get out if getting too deep.
Is there a macro that does it? Which DTE objects to use?
(This is not quite what you're asking for, but almost:)
You can put a breakpoint on every member function of a class in Visual Studio by bringing up the New Breakpoint dialog and entering:
CMyClass::*
See http://blogs.msdn.com/b/habibh/archive/2009/09/10/class-breakpoint-how-to-set-a-breakpoint-on-a-c-class-in-the-visual-studio-debugger.aspx for more details.
Here's a quick implementation of 1800 INFORMATION's idea:
Sub TemporaryMacro()
DTE.ActiveDocument.Selection.StartOfDocument()
Dim returnValue As vsIncrementalSearchResult
While True
DTE.ActiveDocument.ActiveWindow.Object.ActivePane.IncrementalSearch.StartForward()
returnValue = DTE.ActiveDocument.ActiveWindow.Object.ActivePane.IncrementalSearch.AppendCharAndSearch(AscW("{"))
DTE.ActiveDocument.ActiveWindow.Object.ActivePane.IncrementalSearch.Exit()
If Not (returnValue = vsIncrementalSearchResult.vsIncrementalSearchResultFound) Then
Return
End If
DTE.ExecuteCommand("Debug.ToggleBreakpoint")
DTE.ExecuteCommand("Edit.GotoBrace")
DTE.ActiveDocument.Selection.CharRight()
End While
End Sub
I don't know what DTE functions to use, but you could very simply record a macro that could pretty much do it:
Go to the top of the file
ctrl - shift - R (start recording)
ctrl - I (incremental search)
{ (search for the first { character).
F9 (set breakpoint)
ctrl - ] (go to matching } character)
ctrl - shift - R (stop recording)
Now just run this over and over (ctrl - shift P repeatedly) until you reach the end of the file.
If you have namespaces, then change 4. to:
( (search for "(" at the start of the function definition)
esc (stop incremental search)
ctrl - I (incremental search again)
{ (start of function body)
This kind of thing can be infinitely modified to suit your codebase
Like Constantin's method... This seems like windbg territory.
Since you have the cpp, (even if you didn't you could script something to get by), it should be no problem to use logger part of the debugging tools for windows... it's a very handy tool, shame so few people use it.
logger debug's C/COM/C++ easily, with rich symbolic info, hooks/profiling/flexible instrumentation;
One way to activate Logger is to start CDB or WinDbg and attach to a user-mode target application as usual. Then, use the !logexts.logi or !logexts.loge extension command.
This will insert code at the current breakpoint that will jump off to a routine that loads and initializes Logexts.dll in the target application process. This is referred to as "injecting Logger into the target application."
Here's how something similar could be achieved in WinDbg:
bm mymodule!CSpam::*
This puts breakpoint in every method of class (or namespace) CSpam in module mymodule.
I'm still looking for anything close to this functionality in Visual Studio.
There is a macro, but I tested it only with c#.
Sub BreakAtEveryFunction()
For Each project In DTE.Solution.Projects
SetBreakpointOnEveryFunction(project)
Next project
End Sub
Sub SetBreakpointOnEveryFunction(ByVal project As Project)
Dim cm = project.CodeModel
' Look for all the namespaces and classes in the
' project.
Dim list As List(Of CodeFunction)
list = New List(Of CodeFunction)
Dim ce As CodeElement
For Each ce In cm.CodeElements
If (TypeOf ce Is CodeNamespace) Or (TypeOf ce Is CodeClass) Then
' Determine whether that namespace or class
' contains other classes.
GetClass(ce, list)
End If
Next
For Each cf As CodeFunction In list
DTE.Debugger.Breakpoints.Add(cf.FullName)
Next
End Sub
Sub GetClass(ByVal ct As CodeElement, ByRef list As List(Of CodeFunction))
' Determine whether there are nested namespaces or classes that
' might contain other classes.
Dim aspace As CodeNamespace
Dim ce As CodeElement
Dim cn As CodeNamespace
Dim cc As CodeClass
Dim elements As CodeElements
If (TypeOf ct Is CodeNamespace) Then
cn = CType(ct, CodeNamespace)
elements = cn.Members
Else
cc = CType(ct, CodeClass)
elements = cc.Members
End If
Try
For Each ce In elements
If (TypeOf ce Is CodeNamespace) Or (TypeOf ce Is CodeClass) Then
GetClass(ce, list)
End If
If (TypeOf ce Is CodeFunction) Then
list.Add(ce)
End If
Next
Catch
End Try
End Sub
Here's one way to do it (I warn you it is hacky):
EnvDTE.TextSelection textSelection = (EnvDTE.TextSelection)dte.ActiveWindow.Selection;
// I'm sure there's a better way to get the line count than this...
var lines = File.ReadAllLines(dte.ActiveDocument.FullName).Length;
var methods = new List<CodeElement>();
var oldLine = textSelection.AnchorPoint.Line;
var oldLineOffset = textSelection.AnchorPoint.LineCharOffset;
EnvDTE.CodeElement codeElement = null;
for (var i = 0; i < lines; i++)
{
try
{
textSelection.MoveToLineAndOffset(i, 1);
// I'm sure there's a better way to get a code element by point than this...
codeElement = textSelection.ActivePoint.CodeElement[vsCMElement.vsCMElementFunction];
if (codeElement != null)
{
if (!methods.Contains(codeElement))
{
methods.Add(codeElement);
}
}
}
catch
{
//MessageBox.Show("Add error handling here.");
}
}
// Restore cursor position
textSelection.MoveToLineAndOffset(oldLine, oldLineOffset);
// This could be in the for-loop above, but it's here instead just for
// clarity of the two separate jobs; find all methods, then add the
// breakpoints
foreach (var method in methods)
{
dte.Debugger.Breakpoints.Add(
Line: method.StartPoint.Line,
File: dte.ActiveDocument.FullName);
}
Put this at the top of the file:
#define WANT_BREAK_IN_EVERY_FUNCTION
#ifdef WANT_BREAK_IN_EVERY_FUNCTION
#define DEBUG_BREAK DebugBreak();
#else
#define DEBUG_BREAK
#endif
then insert DEBUG_BREAK in the beginning of every function, like this:
void function1()
{
DEBUG_BREAK
// the rest of the function
}
void function2()
{
DEBUG_BREAK
// the rest of the function
}
When you no longer want the debug breaks, comment the line
// #define WANT_BREAK_IN_EVERY_FUNCTION
at the top of the file.