I am using the following code to trap Left/Right/Middle mouse button and mouse row/column in QB45:
(QB45 is Microsoft Quick Basic v4.5)
and I need a way to detect MouseWheel. I have looked at Ralf Brown's interrupt list without luck.
Any ideas? btw: I am using Int 0x33.
The code I am submitting is for the Microsoft Quickbasic IDE and requires the library file QB.QLB.
DECLARE SUB Mouse.Function (Var1, Var2)
DIM SHARED MouseX AS INTEGER, MouseY AS INTEGER
TYPE RegTypeX
AX AS INTEGER
BX AS INTEGER
CX AS INTEGER
DX AS INTEGER
BP AS INTEGER
SI AS INTEGER
DI AS INTEGER
Flags AS INTEGER
DS AS INTEGER
ES AS INTEGER
END TYPE
COMMON SHARED InregsX AS RegTypeX
COMMON SHARED OutregsX AS RegTypeX
DECLARE SUB InterruptX (N AS INTEGER, I AS RegTypeX, O AS RegTypeX)
CALL Mouse.Function(0, 0) ' init mouse
CALL Mouse.Function(1, 0) ' show mouse
DO
IF LEN(INKEY$) THEN
CALL Mouse.Function(2, 0) ' hide mouse
EXIT DO
END IF
' read mouse button press
CALL Mouse.Function(3, 0)
Var2 = INT((OutregsX.CX - 1) / 8 + 1)
Var3 = INT((OutregsX.DX - 1) / 8 + 1)
IF Var3 <> Mouse.Row OR Var2 <> Mouse.Column THEN
CALL Mouse.Function(2, 0) ' hide mouse
Mouse.Row = Var3
Mouse.Column = Var2
PRINT Mouse.Row, Mouse.Column
CALL Mouse.Function(1, 0) ' show mouse
END IF
Mouse.Button = False
CALL Mouse.Function(5, 0)
IF (OutregsX.AX AND 1) = 1 THEN
IF OutregsX.BX > False THEN
Mouse.Button = -1
PRINT "Left-Click"
END IF
END IF
Mouse.Button2 = False
CALL Mouse.Function(5, 1)
IF (OutregsX.AX AND 2) = 2 THEN
IF OutregsX.BX > False THEN
Mouse.Button2 = -1
PRINT "Right-Click"
END IF
END IF
Mouse.Button3 = False
CALL Mouse.Function(5, 2)
IF (OutregsX.AX AND 4) = 4 THEN
IF OutregsX.BX > False THEN
Mouse.Button3 = -1
PRINT "Middle-Click"
END IF
END IF
LOOP
END
SUB Mouse.Function (Var1, Var2)
InregsX.AX = Var1
InregsX.BX = Var2
CALL InterruptX(&H33, InregsX, OutregsX)
END SUB
Related
Could you anybody help me how to split word file by character!
I can't find any way to split word files by the number of characters on the internet!
For example, to split a document into 500-character blocks:
Sub SplitDocument()
Application.ScreenUpdating = False
Dim Rng As Range, i As Long, j As Long
Const Char As Long = 500
With ActiveDocument
' Process each character block
For i = 1 To Int(.Characters.Count / Char)
j = j + 1
' Get the character block
Set Rng = .Range((i - 1) * Char, i * Char)
' Copy the character block
Rng.Copy
Rng.Collapse wdCollapseEnd
Call NewDoc(ActiveDocument, (i - 1) * Char + 1, j)
Next
If Rng.End < .Range.End Then
i = i + 1: j = j + 1
Rng.End = .Range.End
' Copy the range
Rng.Copy
Rng.Collapse wdCollapseEnd
Call NewDoc(ActiveDocument, (i - 1) * Char + 1, j)
End If
End With
Set Rng = Nothing
Application.ScreenUpdating = True
End Sub
Sub NewDoc(DocSrc As Document, i As Long, j As Long)
Dim DocTgt As Document, HdFt As HeaderFooter
' Create the output document
Set DocTgt = Documents.Add(Visible:=False)
With DocTgt
' Paste contents into the output document, preserving the formatting
.Range.PasteAndFormat (wdFormatOriginalFormatting)
' Replicate the headers & footers
For Each HdFt In DocSrc.Sections(DocSrc.Characters(i).Sections(1).Index).Headers
.Sections(1).Headers(HdFt.Index).Range.FormattedText = HdFt.Range.FormattedText
Next
For Each HdFt In DocSrc.Sections(DocSrc.Characters(i).Sections(1).Index).Footers
.Sections(1).Footers(HdFt.Index).Range.FormattedText = HdFt.Range.FormattedText
Next
' Save & close the output document
.SaveAs FileName:=Split(DocSrc.FullName, ".doc")(0) & "_" & j & ".docx", _
FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
.Close SaveChanges:=False
End With
Set DocTgt = Nothing: Set DocSrc = Nothing
End Sub
Using: Firebird 2.5.3
In a stored procedure (PSQL), converting a number from hex notation to decimal notation is done easily:
DECLARE VARIABLE I INTEGER;
BEGIN
I = CAST('0x0FFFE' AS INTEGER); -- I will have the value 65534
How can the reverse be achieved? ie. Convert from decimal notation to hex notation?
Short of using a UDF (which would mean using an external library file), the solution is to write a stored procedure to accomplish this:
SET TERM ^^ ;
CREATE PROCEDURE INTTOHEX (
INPUTNUMBER BigInt)
returns (
OUTPUTNUMBER VarChar(8))
AS
DECLARE VARIABLE Q BigInt;
DECLARE VARIABLE R BigInt;
DECLARE VARIABLE T BigInt;
DECLARE VARIABLE H VARCHAR(1);
DECLARE VARIABLE S VARCHAR(6);
begin
/* Max input value allowed is: 4294967295 */
S = 'ABCDEF';
Q = 1;
OUTPUTNUMBER = '';
T = INPUTNUMBER;
WHILE (Q <> 0) DO
BEGIN
Q = T / 16;
R = MOD(T, 16);
T = Q;
IF (R > 9) THEN
H = SUBSTRING(S FROM (R-9) FOR 1);
ELSE
H = R;
OUTPUTNUMBER = H || OUTPUTNUMBER ;
END
SUSPEND;
end ^^
SET TERM ; ^^
You can call this stored procedure from standard SQL or another stored procedure like this:
For example:
SELECT OUTPUTNUMBER FROM INTTOHEX(65534);
just did a short firebird function,
could handle bigger number,
maybe could help someone
CREATE OR ALTER FUNCTION INT64TOHEX (
C BIGINT)
RETURNS VARCHAR(32)
AS
DECLARE VARIABLE IREM INTEGER;
DECLARE VARIABLE HEX VARCHAR(32);
BEGIN
IREM = MOD(C, 0XFF);
HEX = '';
WHILE (IREM > 0) DO
BEGIN
HEX = SUBSTRING('0123456789abcdef' FROM BIN_SHR(BIN_AND(C, 0XFF), 4) + 1 FOR 1) || SUBSTRING('0123456789abcdef' FROM BIN_AND(BIN_AND(C, 0XFF), 15) + 1 FOR 1) || HEX;
C = BIN_SHR(C, 8);
IREM = MOD(C, 0XFF);
END
RETURN TRIM(HEX);
END
I don't know why but I am getting this error:
Error in mr_lsbpex (line 3)
dlen = uint32(0) ;
Output argument "a" (and maybe others) not assigned during call to "E:\path\mr_lsbpex.m>mr_lsbpex"
I have tested "dlen = uint32(0) ;" in matlab enviorment (outside of this function) and everything was OK. Here is my code:
function a = mr_lsbpex ( r, p )
% extract from an array
dlen = uint32(0) ;
s = size (r) ;
rnd = rand (s(1),s(2)) ;
rd = 32 ;
rl = s(2) ;
for i=1:s(2)
if rnd(1,i)<rd/rl
d = bitget (round(r(1,i)/p),1);
dlen = bitset (dlen,rd,d);
rd = rd -1 ;
end
rl = rl -1 ;
end
if (dlen > 10000000 )
clear a ;
return ;
end
a = uint8(zeros(dlen,1)) ;
rd = double(dlen * 8) ;
rl = double(s(1)*s(2)-s(2)) ;
for i=2:s(1)
for j=1:s(2)
if rnd(i,j)<rd/rl
d = bitget (round(r(i,j)/p) ,1) ;
a = z_set_bit (a,rd,d) ;
rd = rd - 1 ;
end
rl = rl - 1 ;
end
end
Remember: a needs to be returned ALLWAYS!
The error is not in that specific line, but in the "whole" function itself.
Your problem is that Matlab thinks that a its not going to be created. And actually in some case it may not be created.
The following line in the beginning of your function should do the trick
a=0; % well, or a=NaN; or whatever you want to return
Additionally, don't clear a in if (dlen > 10000000 ).
I'm currently trying to implement a Clark & Wright Savings Heurisitc in VBA, but I'm currently facing some problem. I'm fairly new to VBA, and this error (91) keeps apearing on similar situations, which lead me to believe I'm missing some crucial knowledge. Next I present you the code:
Public Sub CWsavings()
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim aux As Integer
Dim d As Integer
Dim r As Integer
Dim Cu(200) As customer
Dim De(12) As Depot
For i = 1 To 200
Set Cu(i) = New customer
Cu(i).custID = i
Cu(i).longitude = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 2)
Cu(i).latitude = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 3)
Cu(i).lt = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 4)
Cu(i).et = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 5)
Cu(i).weekdemand = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 6)
Cu(i).peakdemand = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 7)
Cu(i).D1 = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 8)
Cu(i).D2 = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 9)
Next i
For j = 1 To 12
Set De(j) = New Depot
De(j).depotID = j
De(j).Dname = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 13)
De(j).latitude = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 14)
De(j).longitude = ThisWorkbook.Sheets("Folha1").Cells(i + 1, 15)
De(j).ncust = ThisWorkbook.Sheets("Results").Cells(j, 7)
De(j).nroute = 0
For k = 1 To De(j).ncust
aux = ThisWorkbook.Sheets("Results").Cells(j + 1, 10 + k)
Call De(j).SetCustomer(Cu(aux), k)
Next k
Next j
For d = 1 To 12
Dim M(30, 30) As Double
Dim maxsav As Double
Dim maxpos(2) As Integer
Dim connorder(676, 2) 'order of connections for routing
Dim it As Integer
it = 0
For i = 1 To De(d).ncust
For j = 1 To De(d).ncust
M(i, j) = CalcSavings(De(d), De(d).customer(i), De(d).customer(j)) ' error here
Next j
Next i
itbegin:
maxsav = 0
maxpos(1) = 0
maxpos(2) = 0
For i = 1 To De(d).ncust
For j = 1 To De(d).ncust
If i <> j Then
If M(i, j) > maxsav Then
maxsav = M(i, j)
maxpos(1) = i
maxpos(j) = j
End If
End If
Next j
Next i
it = it + 1
connorder(it, 1) = maxpos(1)
connorder(it, 2) = maxpos(2)
If it < De(d).ncust * De(d).ncust - ncust Then
M(maxpos(1), maxpos(2)) = 0
GoTo itbegin
End If
Next d
End Sub
Public Function CalcSavings(d As Depot, C1 As customer, C2 As customer)
Dim id As Double
Dim dj As Double
Dim ij As Double
id = DeptDist(C1, d)
dj = DeptDist(C2, d)
ij = CustDist(C1, C2)
CalcSavings = id + dj - ij
End Function
The class Depot:
Public depotID As Integer
Public Dname As String
Public latitude As Double
Public longitude As Double
Private customers(200) As customer
Public ncust As Integer
Private routes(500) As route
Public nroute As Integer
Public Sub addcust(C As customer)
ncust = ncust + 1
Set customers(ncust) = C
End Sub
Public Sub addroute(R As route)
nroute = Me.nroute + 1
Set routes(Me.nroute) = R
End Sub
Public Property Get customer(i As Integer) As customer
customer = customers(i)
End Property
Public Sub SetCustomer(C As customer, i As Integer)
Set customers(i) = C
End Sub
Public Property Get route(i As Integer) As route
route = routes(i)
End Property
Public Sub SetRoute(R As route, i As Integer)
Set routes(i) = R
End Sub
(Class depot Updated)
And the class Customer:
Public custID As Integer
Public latitude As Double
Public longitude As Double
Public lt As Double
Public et As Double
Public weekdemand As Integer
Public peakdemand As Integer
Public D1 As Integer
Public D2 As Integer
I'm sorry for the long post, any help would be appreciated.
Final answer...
VERY ODDLY, (not that odd, when you really look at it, but) you need to use Set even in your Get properties. I guess the reason behind this is because you're returning an object, and even though that object may already exist, you're not going to use that very object. A copy is used instead and Set becomes vital to initialize that copy.
For example, here's what your "get customer" should look like :
Public Property Get customer(i As Integer) As customer
Set customer = customers(i)
End Property
I guess it all makes sense; your array is private, and therefore you wouldn't want to pass the exact object that is contained inside that array, or it'd be counter-logic.
I think I found it... again...!
Try this :
Public Sub SetCustomer(C As customer, i As Integer)
Set customers(i) = C
End Sub
Notice customer(i) was replaced by customers(i)
EDIT : Deleted previous answer, as I was mostly fishing.
I have 3 tables in a single form, they use SQL queries to select the data. I need to refresh them somehow, but nothing works.
E.g. this doesn't work at all:
oBaseContext = CreateUnoService("com.sun.star.sdb.DatabaseContext")
oDataSource = oBaseContext.getByName(dbName)
oCon = oDataSource.getConnection("", "")
oCon.getTables().refresh()
And this updates only the first table:
oDisp = createUnoService("com.sun.star.frame.DispatchHelper")
oFrame = ThisComponent.getCurrentController().getFrame()
oDisp.executeDispatch(oFrame, ".uno:Refresh", "", 0, Array())
How do I update them all?
Oh my god, it was so easy, I feel dumb now:
Sub reloadAllTables
Dim Forms : Forms = ThisComponent.DrawPage.Forms
Dim i%
For i = 0 To Forms.getCount()-1
Forms.getByIndex(i).reload()
Next
End Sub
Reloading forms doesn't refresh tables, table controls are refreshed by using .refresh on each column, for example-
SUB refreshTables(oForm as object)
DIM cnt as integer, cnt2 as integer, tot as integer, tot2 as integer
DIM oFormObj as object
'get number of form object
tot = oForm.getCount - 1
IF tot > -1 THEN
FOR cnt = 0 TO tot
'next form object
oFormObj = oForm.getByIndex(cnt)
'is object a table control AKA grid control
IF oFormObj.ImplementationName = "com.sun.star.comp.forms.OGridControlModel" THEN
'refresh each column
tot2 = oFormObj.getCount - 1
IF tot2 > -1 THEN
FOR cnt2 = 0 TO tot2
oFormObj.getByIndex(cnt2).refresh
NEXT
ENDIF
ENDIF
NEXT
ENDIF
END SUB