dcsimg
Results 1 to 9 of 9

Thread: [RESOLVED] Translation to VB.NET

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2016
    Location
    Slovenia
    Posts
    550

    Resolved [RESOLVED] Translation to VB.NET

    Hi guys,

    I'm trying to get my C# code translated into VB.NET but I'm facing troubles, so I turned to you guys.
    Code is for re-positioning messagebox to desired location (not just center of screen) and code works fine in C#.

    Here is original C# code in question:

    Code:
     private void MoveMsgBox(int x, int y, bool repaint, string title)
            {
                Thread thr = new Thread(() => // New thread
                {
                    IntPtr msgBox = IntPtr.Zero;
                   
                    while ((msgBox = FindWindow(IntPtr.Zero, title)) == IntPtr.Zero) ;
    
                    Rectangle r = new Rectangle();
                    GetWindowRect(msgBox, out r); 
                    MoveWindow(msgBox 
                       r.Width - r.X 
                       r.Height - r.Y
                       repaint);
                });
                thr.Start();
            }

    And my full- translated code in VB.NET:

    Code:
    <DllImport("user32.dll")>
        Private Shared Function FindWindow(ByVal classname As IntPtr, ByVal title As String) As IntPtr
        End Function
    
        <DllImport("user32.dll")>
        Private Shared Sub MoveWindow(ByVal hwnd As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal rePaint As Boolean)
        End Sub
    
        <DllImport("user32.dll")>
        Private Shared Function GetWindowRect(ByVal hwnd As IntPtr, <Out> ByRef rect As Rectangle) As Boolean
        End Function
    
      Private Sub MoveMsgBox(ByVal x As Integer, ByVal y As Integer, ByVal repaint As Boolean, ByVal title As String)
            Dim thr As Thread = New Thread(Sub()
                                               Dim msgBox As IntPtr = IntPtr.Zero
    
                                               While msgBox= FindWindow(IntPtr.Zero, title) = IntPtr.Zero
                                               End While
    
                                               Dim r As Rectangle = New Rectangle()
                                               GetWindowRect(msgBox, r)
                                               MoveWindow(msgBox, r.Width - r.X, r.Height - r.Y, repaint)
                                           End Sub)
            thr.Start()
        End Sub
    There is no error in code, but "msgbox" allways returns 0 from FindWindow function. Any help kindly appreciated, thanks in advance.

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    33,759

    Re: Translation to VB.NET

    msgBox is a particularly poor choice for a variable name in VB, since there is a function of the same name. So, the first thing to do is to change the name of that variable to something that isn't a function. That shouldn't be an issue, since the declaration of the local variable should hide the function, but it's still a wiser choice.

    This line is also a bit of a mess:

    While msgBox= FindWindow(IntPtr.Zero, title) = IntPtr.Zero

    What that will do is evaluate

    FindWindow(IntPtr.Zero, title) = IntPtr.Zero

    which will be either True or False, then assign that to msgBox, which is not a Boolean, but an IntPtr, so you'd be coercing True/False into an IntPtr. What the C# code is doing is calling this:

    msgBox= FindWindow(IntPtr.Zero, title)

    to set msgBox to the return value from FindWindow, then comparing msgBox to IntPtr.Zero to determine whether or not to loop. I'm not sure that there is a direct, one-line, drop in replacement in VB, since there is no == operator, so the = sign does double duty. You need to do the assignment, then a comparison. Two steps.

    However, That seems like a horrible solution, if I'm understanding it right. FindWindow should return a windows handle if the exact title is found on a window, otherwise, I think it will return a null pointer. So, the While loop will keep running until FindWindow returns something other than IntPtr.Zero, which it will do readily enough if there is a window with the right title. But if there isn't a window with the right title, why won't it just keep searching forever in a frantic busy loop? Because it's in a thread, you may never know, so the result of that method could be a proliferation of busy loops spinning away forever, gobbling up CPU resources as fast as they become available, until you terminate the increasingly sluggish program in frustration.
    My usual boring signature: Nothing

  3. #3
    Fanatic Member
    Join Date
    Jan 2006
    Posts
    664

    Re: Translation to VB.NET

    As Shaggy Hiker already said, rename from msgBox to something else.
    Also, you can't assign to a variable within a condition like you can in C# (because VB uses the same operator for both assignment and equality), so you have to repeat the assignment just before and within the loop.

    Code:
     Private Sub MoveMsgBox(ByVal x As Integer, ByVal y As Integer, ByVal repaint As Boolean, ByVal title As String)
    			Dim thr As Thread = New Thread(Sub()
    				Dim box As IntPtr = IntPtr.Zero
    
    				box = FindWindow(IntPtr.Zero, title)
    				Do While box = IntPtr.Zero
    					box = FindWindow(IntPtr.Zero, title)
    				Loop
    
    				Dim r As New Rectangle()
    				GetWindowRect(box, r)
    				MoveWindow(box r.Width - r.X r.Height - r.Y repaint)
    			End Sub)
    			thr.Start()
     End Sub
    However, I've approached this purely from a code translation perspective. The loop may be misguided to begin with, as suggested by Shaggy Hiker.
    Last edited by David Anton; May 14th, 2019 at 09:19 AM.
    David Anton
    Convert between VB, C#, C++, & Java
    www.tangiblesoftwaresolutions.com

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2016
    Location
    Slovenia
    Posts
    550

    Re: Translation to VB.NET

    Thanks guys, both of you, specially David for code example. My code now works in VB.NET too.

    However, That seems like a horrible solution, if I'm understanding it right. FindWindow should return a windows handle if the exact title is found on a window, otherwise, I think it will return a null pointer. So, the While loop will keep running until FindWindow returns something other than IntPtr.Zero, which it will do readily enough if there is a window with the right title. But if there isn't a window with the right title, why won't it just keep searching forever in a frantic busy loop? Because it's in a thread, you may never know, so the result of that method could be a proliferation of busy loops spinning away forever, gobbling up CPU resources as fast as they become available, until you terminate the increasingly sluggish program in frustration.
    To answer this : I've never thought in a way like this. I use this code quite long time and so far I haven't received any complaint from users. If that happens someday I hope I'll remember your explanation

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    33,759

    Re: Translation to VB.NET

    You won't get complaints...ever...in most cases. For one thing, if FindWindow finds a window, then the While loop is useless, since it exits the first time, but also quite harmless. The case where a problem would arise would be if FindWindow doesn't find a window, which seems very unlikely to ever happen. If it does happen, then one core should be pretty much pegged, but on modern systems, it's likely that nobody would ever notice. If it happens more than once, the behavior can be pretty complicated. If all the threads have affinity for one core, then they will all contest for that core, and may only conflict with each other, so users may not notice.

    It would be an interesting thing to test. For example, you might arrange it such that the code is run when FindWindow certainly will NOT find a window (for example, have it search for some random string of characters). You can either step through the code to see if it sits and spins. If it does, then you might try running that while watching the resource monitor to see if one CPU pegs, or even watch power consumption on the system when the process is called, as you will see it spike upwards significantly (you may also hear the cooling fans ramp up, if they make enough noise, because they'll work harder to shed the extra heat being generated).

    Still, the most likely case would normally be that FindWindow always finds a window, in which case the loop exits immediately. That design makes me really nervous, but it's quite likely that nobody has ever seen the bad scenario occur, or noticed when it did. With one core, they would, if it happened, but with multiple cores...it'll only raise their electric bill if it happens, and probably only by pennies.
    My usual boring signature: Nothing

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2016
    Location
    Slovenia
    Posts
    550

    Re: [RESOLVED] Translation to VB.NET

    Well, I never investigated this to see what is really happening in background. I found these lines of code somewhere and have used It ever since.

    And to be honest, code isn't quite understandable to me. You have to call this method before you call "Messagebox.Show", so I don't really understand how FindowWindow API can find Msgbox
    handle If I call It after this method. Example of usage:

    Code:
            MoveMsgBox(x, y, True, "Some title")
            MessageBox.Show("This is a test MessageBox.", "Some title", MessageBoxButtons.OK, MessageBoxIcon.Information)

  7. #7
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    102,245

    Re: [RESOLVED] Translation to VB.NET

    Quote Originally Posted by LuckyLuke82 View Post
    I don't really understand how FindowWindow API can find Msgbox
    handle If I call It after this method.
    It's because that MoveMsgBox method starts a new thread and the code in that new thread loops continually until it finds the specified window. When you call MessageBox.Show, it creates that window so the code executing in the other thread finds it and moves it, then terminates that thread. Think of it like this. MoveMsgBox is a person. That person goes and finds another person and tells them to go outside and look for a red balloon and put it in a box. That first person then then comes back to you. You then tell a third person to blow up a red balloon and throw it out the window. They do just that. The second person who was outside looking then finds that balloon and puts it in the box. Simple, right? That's multi-threading for you. MoveMsgBox is able to start some code executing and then return while that code continues to execute, so something can happen as a result of that method call even after it returns.

  8. #8
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    40,904

    Re: [RESOLVED] Translation to VB.NET

    A MessageBox is a modal dialog, so as soon as you call .Show() no more of your code runs until the MessageBox is closed.

    As such, putting code after MessageBox.Show() cannot have an effect on it.

    The MoveMsgBox routine creates a new thread (basically a separate program that runs independently of your main program), and it just keeps trying to find the MessageBox (the Do Loop) until it finds it. Then it moves that window, and exits the thread.

    Unfortunately as mentioned above, if for any reason it fails to find the window, the thread will only end when your program does - and until then it will be keeping the computer busy (and if you get to about 4 threads doing that, the computer could become unusable).


    I would be tempted to make the loop more like this (untested):
    Code:
    				Dim endTime as DateTime = DateTime.Now.AddSeconds(2)
    				box = FindWindow(IntPtr.Zero, title)
    				Do While box = IntPtr.Zero
    					Thread.Sleep(20)
    					box = FindWindow(IntPtr.Zero, title)
    					If DateTime.Now >= endTime Then Exit Sub
    				Loop
    This will use less processor time (but still be fast enough to make little/no difference to behaviour), and will automatically stop if it doesn't find the MessageBox within 2 seconds.

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2016
    Location
    Slovenia
    Posts
    550

    Re: [RESOLVED] Translation to VB.NET

    Thanks for further explanation si_the_geek, now I completely understand. Your code-change suggestion is also noted and allready included, thanks for that

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width