SetConsoleCursorPosition API Fails

Paste the following code in a module and run the code using Main() as the startup object.

Can anyone tell me why the SetConsoleCursorPosition API fails?

Thanks.


Option Explicit
Type COORD
        x As Integer
        y As Integer
End Type
Public Const STD_INPUT_HANDLE = -10&
Public Const STD_OUTPUT_HANDLE = -11&
Public Const STD_ERROR_HANDLE = -12&
Public hStdIn  As Long   ' handle of Standard Input
Public hStdOut As Long   ' handle of Standard Output
Public hStdErr As Long   ' handle of Standard Error Output
Declare Function AllocConsole Lib "kernel32" () As Long
Declare Function FreeConsole Lib "kernel32" () As Long
Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long
Declare Function SetConsoleCursorPosition Lib "kernel32" _
    (ByVal hConsoleOutput As Long, dwCursorPosition As COORD) As Long
Declare Function ReadFile Lib "kernel32" _
    (ByVal hFile As Long, _
    lpBuffer As Any, _
    ByVal nNumberOfBytesToRead As Long, _
    lpNumberOfBytesRead As Long, _
    lpOverlapped As Any) As Long
Declare Function WriteFile Lib "kernel32" _
    (ByVal hFile As Long, _
    ByVal lpBuffer As String, _
    ByVal nNumberOfBytesToWrite As Long, _
    lpNumberOfBytesWritten As Long, _
    lpOverlapped As Any) As Long

Sub Main()
      Dim Lbuf As String
      AllocConsole
      hStdIn = GetStdHandle(STD_INPUT_HANDLE)
      hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)
      hStdErr = GetStdHandle(STD_ERROR_HANDLE)
      if setcpos(5,5) = true then
            cWrite "SetConsoleCursorPosition API Passed!"
      else
            cWrite "SetConsoleCursorPosition API Failed!"
      End If
      cWrite "Press Enter:"
      Lbuf = cRead
      FreeConsole
      End
End Sub
            
Function SetCpos(Row As Integer, Col As Integer) As Boolean
      Dim lInfo As COORD
      lInfo.x = Col
      lInfo.y = Row
      If Not SetConsoleCursorPosition(hStdOut, lInfo) = 0 Then SetCpos = True
End Function

Sub cWrite(lString As String, Optional Binary As Boolean)
    Dim lBytesWritten As Long
    Dim s As String
    s = IIf(Binary = True, lString, lString & vbCrLf)
    WriteFile hStdOut, s, Len(s), lBytesWritten, ByVal 0&
End Sub

Function cRead(Optional BufferSize As Long) As String
    Dim sBuf As String
    Dim BytesRead As Long
    Dim Retcode As Long
    Dim sBufSize As Long
    sBufSize = IIf(BufferSize = 0, 2048, BufferSize)
    sBuf = String(sBufSize, Chr$(0))
    Retcode = ReadFile(hStdIn, ByVal sBuf, sBufSize, BytesRead, ByVal 0&)
    cRead = Left$(sBuf, BytesRead - 2)
End Function
 
mikieacAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mikieacAuthor Commented:
Adjusted points to 250
0
mikieacAuthor Commented:
Adjusted points to 350
0
mikieacAuthor Commented:
I guess this was harder than I thought... Anybody have any ideas?
0
The Ultimate Tool Kit for Technolgy Solution Provi

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy for valuable how-to assets including sample agreements, checklists, flowcharts, and more!

danelroismanCommented:

Hi!

Function SetCpos(Row As Integer, Col As Integer) As Boolean

'get handle to stdout here!
'!!!!!!!!!!!!!!!!!!!!!!
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)
'!!!!!!!!!!!!!!!!!!!!!!!

Dim lInfo As COORD
lInfo.x = Col
lInfo.y = Row
If Not SetConsoleCursorPosition(hStdOut, lInfo) = 0 Then SetCpos = True
End Function


Daniel

0
mikieacAuthor Commented:
Adjusted points to 450
0
mikieacAuthor Commented:
Sorry, that doesn't work.  hStdOut is a global variable.  Once it gets set in Main(), it doesn't change.

0
mcriderCommented:
It's not your fault... Blame Microsoft!

The reason the SetConsoleCursorPosition function fails is it is declared incorrectly in the API text viewer.  It is defined like this:

     Declare Function SetConsoleCursorPosition _
          Lib "kernel32" (ByVal hConsoleOutput As Long, _
          dwCursorPosition As COORD) As Long

The problem is, the 2nd argument "dwCursorPosition" must be passed ByVal, not ByRef.  If you don't specify ByVal, ByRef is the default in Visual Basic... HOWEVER... VB will not let you pass a user-defined type ByVal.

This means you have to define the function like this:

     Declare Function SetConsoleCursorPosition _
          Lib "kernel32" (ByVal hConsoleOutput As Long, _
          ByVal dwCursorPosition As Long) As Long

Now, you have to fit the X/Y values that used to be assigned with the COORD type into a Long type.  You can do this by adding this function to your module:

     Function cvtCoordToLng(wHi As Integer, wLo As Integer) As Long
        cvtCoordToLng = (wHi * &H10000) Or (wLo And &HFFFF&)
     End Function


Then when you call the SetConsoleCursorPosition API, you want to do it like this:

     Dim Row As Integer
     Dim Col As Integer
     Dim rVal As Long
     'SET Row and Col to the proper values here
     rVal = SetConsoleCursorPosition(hStdOut, cvtCoordToLng(Row, Col))


Hope this helps!


Cheers!
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
RuchiCommented:
As I read the MSDN library article about SetConsoleCursorPosition API, it says,"
When a screen buffer's cursor is visible, its appearance can vary, ranging from completely filling a character cell to showing up as a horizontal line at the bottom of the cell. The dwSize member of the CONSOLE_CURSOR_INFO structure specifies the percentage of a character cell that is filled by the cursor. If this member is less than 1 or greater than 100, SetConsoleCursorInfo fails."

Also, you must declare the headers -- Wincon.h and Windows.h in C++ or C or Visual C++. This API may not work with VB, doesn't it?

0
mcriderCommented:
Ruchi & mikieac,

Try the code with the modifications I suggested, and the API will work!


Cheers!
0
mikieacAuthor Commented:
mcrider, you are amazing!  This works perfectly!!!!!

Thank-you so much.
0
mcriderCommented:
Thanks for the points! Glad I could help!


Cheers!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.