Thread: Sending WM_SETCURSOR to different windows

  1. #1
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446

    Sending WM_SETCURSOR to different windows

    Let's see if I can get this answered here instead...

    A little background just in case you are wondering why I am doing this:

    In C#, Application.UseWaitCursor changes the cursor shape to the default hourglass shape without waiting for WM_SETCURSOR response. This means that the cursor shape doesn't last. It is set again immediately to Cursor.Current based on whatever control my mouse cursor is currently hovering.

    As I understand this is by design and I'm fine with it. It only means I have to manually send WM_SETCURSOR after Application.UseWaitCursor. Without doing it, I cannot have the behavior I intend below.

    .............

    I need for the mouse cursor to change to an hourglass while waiting for a form to load that it's taking a few seconds to display. This form does some data processing before displaying its contents.

    This is what I came up with.

    Code:
    static class NativeMethods
    {
        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
    
        public static void SwitchWaitCursor(IntPtr handle)
        {
            Application.UseWaitCursor = !Application.UseWaitCursor;
            SendMessage(handle, 0x20, handle, (IntPtr)1);
        }
    
        /*...*/
    }
    And I use it like this:

    Code:
    // When calling the slow form
    
    NativeMethods.SwitchWaitCursor(this.Handle);
    using (SlowForm diag = new SlowForm())
    {
        diag.ShowDialog(this);
    }
    
    
    // OnShow() of the SlowForm
    
    private void SlowForm_Shown(object sender, EventArgs e)
    {
        NativeMethods.SwitchWaitCursor(this.Handle);
    }
    It is working exactly as expected. However, I do have one thought nagging me. Is it alright in this SendMessage usage pattern, for hWnd to refer to two different windows?
    Last edited by Mario F.; 12-09-2009 at 08:38 AM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  2. #2
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Hmm... Should I improve the question in any way?
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  3. #3
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    I am not sure exactly what you want but SetCursor() can be used with different/same HWNDs.

    A child can send the parent HWND to set the cursor for all children.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  4. #4
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Doesn't work novacain. The reason I need this is because the window will only show some 3 to 5 seconds after being called. So there is this moment between clicking the button on the main form and the called form actually starting to paint.

    SetCursor() will only take effect during, right before, or after the Paint event. I'm not really sure which. You can easily test this by trying to set up a waiting cursor on a form in which constructor you spend a lot of time. You can't. Not through normal means (Form.CurrentCursor, Form.SetCursor, Form.UseWaitCursor, Application.UseWaitCursor)

    Now, my approach works, mind you. That's not the problem. I'm just wondering if there are any side effects I'm not aware to having WM_SETCURSOR being sent to two different windows.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  5. #5
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Depending on the situation...

    I use a (threaded) progress bar dialog to show progress for lenghty loads (ie form needs to extract data from DB prior to becomming visible) rather than changing the cursor.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  6. #6
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    It occurred to me. Also thought of simply moving the pre-processing logic out of the form constructor and into the shown event. There I can set easily set the cursor behavior. It's only transitions across forms that complicate controlling the cursor image.

    But...

    - A progress bar can easily become an unnecessary nag on fast computers or future computers. Note that these 5 seconds processing happen on my E4500 2.20 Ghz Dual core. The cursor shape is a much more innocuous option.

    - Delaying the pre-processing logic until after the form loads is often an ugly solution I don't like to see in other programs. That is, I find it more aesthetically pleasing to wait for a form to load, that to be looking at a useless form while I wait for it to populate the controls or do whatever else it needs to do before I can use it.

    ...

    So, again, my solution works. And it does things as I like them. Let's not discuss that anymore, ok.

    My one and only question is if in the way i'm currently doing it, whether sending WM_SETCURSOR to two different windows will have any side-effects. I didn't know this question was worth so much debate without even an attempt at answering it. Sheesh! (But rest assured I will not be waiting for such answer. I think it's best I find the answer myself)
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  7. #7
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Code:
    private void SlowForm_Shown(object sender, EventArgs e)
    {
        NativeMethods.SwitchWaitCursor(ParentForm.Handle);
    }
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  8. #8
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    I'll leave it to you to answer why that would throw a null reference object exception. I don't even need to test it to see that happening. Instead you want the Owner property.

    I told you before I don't want a solution. If I did, I would just store the main form handle on a NativeMethods field and clean it when resetting Application.UseWaitCursor.
    I thought it was clear my question has nothing to do with a solution. I can see you are just wasting my time. Have a nice day.
    Last edited by Mario F.; 12-11-2009 at 07:44 AM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  9. #9
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Sorry I am not tring to waste your time.

    As I tried to say the first post, SET CUSROR is always reflected to the parent, the parent can cancel the change. This gives a central point so only one HWND could be used and shows that differing child HWNDs can, by design, set the cusor.

    I then offered an alternate. I think putting long processing in a constructor poor design (each to their own).

    I then tried to point out that you have many ways (globals, parent obj or params) to pass the same HWND to the second call and remove the issue. This means the same HWND would be used in both calls.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  10. #10
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Fair enough novacain. But it's not that simple:

    Quote Originally Posted by novacain View Post
    As I tried to say the first post, SET CUSROR is always reflected to the parent, the parent can cancel the change. This gives a central point so only one HWND could be used and shows that differing child HWNDs can, by design, set the cusor.
    And yet I already have an answer to my question (I did some research, which I was hoping to avoid with a straight answer here). And that is, there is no problem sending WM_SETCURSOR to a child window to cancel a WM_SETCURSOR sent to a parent.

    I then offered an alternate. I think putting long processing in a constructor poor design (each to their own).
    Definitely to each their own. The logic of application design is not always compatible with what is right or what is wrong. On this case, preprocessing is needed because the form is constructed dynamically from data on a DB.

    I then tried to point out that you have many ways (globals, parent obj or params) to pass the same HWND to the second call and remove the issue. This means the same HWND would be used in both calls.
    And here comes the important bit

    It could, because you are not thinking outside the box. You looked at my code and assumed the problem domain is resumed to that. And yet, I will need to use that in other scenarios, including on forms without a owner form called from an argument-less Show(), or on forms whose owner is not accessible for any other reason.

    You can ask, why don't I simply overload NativeMethods.SwitchWaitCursor() to account for other usage scenarios? I'm fully aware of the potential choices in front of me. I was not asking for help. Were I, and you would know it. My one and only concern was about WM_SETCURSOR.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Anyone using Windows 7?
    By Sharke in forum General Discussions
    Replies: 60
    Last Post: 07-12-2009, 08:05 AM
  2. Dialog Box Problems
    By Morgul in forum Windows Programming
    Replies: 21
    Last Post: 05-31-2005, 05:48 PM
  3. dual boot Win XP, win 2000
    By Micko in forum Tech Board
    Replies: 6
    Last Post: 05-30-2005, 02:55 PM
  4. SDL and Windows
    By nickname_changed in forum Windows Programming
    Replies: 14
    Last Post: 10-24-2003, 12:19 AM
  5. IE 6 status bar
    By DavidP in forum Tech Board
    Replies: 15
    Last Post: 10-23-2002, 05:31 PM