Jump to content

Window Move Event?


rpodsim

Recommended Posts

I am trying to find a way to determine if the VI Window has been moved. I have gone through the events and can't find anything for the window moving. I tried using the Mouse up event but that only works for the pane not the panel or application.

I have an application that has a set of selectable windows for displaying various data and would like to tie the position of the selectable windows to the position of the main application window. I could use polling for the position of the main VI but that seems like a waste of CPU time, so I was looking for some sort of event to handle that case.

If anyone has a idea on where to look or how to proceed, I would be grateful.

Link to comment

There is currently no event-based way to determine if a VI's panel is moved. The previous two suggestions (your suggest of polling, and Aristos' suggestion of Windows DLL calls) are the only options. I have used the polling technique to link VI windows before...it's rather choppy. If you end up getting a decent implementation of the Windows calls working, I'd like to see it.

-D

Link to comment

It's probably been a decade since I've played with MFC, but this thread brings a few ideas to mind. I'm rusty enough that I won't be able to provide a solution, but I can point out a few things that might get you rolling since restricting yourself to Windows system calls seems to be ok.

SetWindowPos (user32.dll) is the function you need to move a window using system calls, you'll need to get your window's handle, I've seen discussions on how to do this on lava. It ultimately just boils down to another function call from user32 I think. Note there's some funky session isolation security issues that creep up on Vista, I have absolutely no clue as to whether or not they'll come into play.

WM_MOVE is one of the related signals you might wish to receive, the message is broadcast whenever the window moves. The caveat is I have absolutely no idea how to hook into it from LabVIEW. It's trivial in MFC where you use a C++ macro, but...

In general, the MSDN reference for Windowing: Windows gives a pretty good overview of how the system manages window resources.

I wouldn't be surprised if there isn't a higher level of abstraction available through .NET calls.

Link to comment

QUOTE (Ton @ Jan 27 2009, 11:14 PM)

Maybe any of the http://wiki.lavag.org/Private_events' rel='nofollow' target="_blank">Private events?

Especially VI Redraw and VI Scroll, I think VI Redraw is the one you should study.

None of the private events fire for this. Events in LV are only for things within LV. To the best of my knowledge, none has ever been added for items outside of LV... and, believe it or not, window position is not "inside LV". It is a purely OS event that LV doesn't have to react to for any reason, so it isn't one for which LV itself registers, thus it isn't available to pass along to users.
Link to comment

QUOTE (MJE @ Jan 28 2009, 12:10 AM)

http://msdn.microsoft.com/en-us/library/ms633545%28VS.85%29.aspx' rel='nofollow' target="_blank">SetWindowPos (user32.dll) is the function you need to move a window using system calls, you'll need to get your window's handle, I've seen discussions on how to do this on lava.

Here's a couple of VIs that should help with that.

Link to comment

You can set the window position and size using the VI properties, so there's no need to call into the OS API for that part. In any case, I have a feeling that whichever method you choose will have the choppiness Darren was refering to, because even if you get the event, I'm not sure you'll be able to preempt it so that you can move your second window before the first window move is drawn. In that case, I don't think you'll get any better performance from events than from polling. That said, I'm far from an expert on the Windows API.

An alternate implementation would be to use subpanels. This will include some overhead, as you'll need to build the "windowing" yourself, but you might be able to do this nicely using panes and automatically resizing the subpanels to fit the panes.

Link to comment

Is this what you are trying to do:

Display:

Show a main window

Show one or more child windows relative to main window

Event Responses:

Whenever the main window moves, you want each child window to follow the main window with a certain offset.

Whenever one or more child windows move, you want the parent window to move the same way.

(I guess you are looking for behavior similar to WinAmp 3.0? where your playlist would snap to the player...etc)

Well, I have done something very similar - and many people like to call it "snapping".

Basically what I did was start sniffing the Windows Messages of the main window from each child window, and whenever a move was detected I would set a local boolean variable to "true", and move that corresponding child window. And the boolean variable would disable the sniffing of windows messages until the move was finished.

And I did the opposite for the main window listening to each child window.

This shouldn't scare you to implement in LabVIEW, but I do recommend using an iterative approach, let me know if this is what you intend to do.

Link to comment

Thanks for the help. :worship:

So far I can get the window handler. Courtesy of crelf.(much prettier icon then I had :thumbup: ) I was trying to use the GetMessage() function, but I'm stuck on how to access the message element of the MSG structure as the GetMessage function uses a pointer to the MSG. :headbang:

I am looking at using a CIN and writing a wrapper to access the message.(Doing the research on that now)

I was hoping though that someone would know an easier way to access the data being pointed to, perhaps some way to get that data to a cluster? :question:

John:

That is exactly what I'm looking for. I'm primarily looking at the first response, though implementing both would be desirable. One step a time. :)

From what you described, I seem to be on a similar track to solving this. Just seem to be having trouble with the details.

Link to comment

QUOTE (john@aleconsultants.com @ Jan 28 2009, 02:29 PM)

Got an example you care to post?

QUOTE (rpodsim @ Jan 28 2009, 02:48 PM)

So far I can get the window handler. Courtesy of crelf.(much prettier icon then I had :thumbup: )

Anytime :)

Link to comment

I just saw something quite interesting in the MSDN....

You can easily hook into the events of another window/form/control by using the Control.FromHandle(IntPtr Handle) static member to create a new Control type.

All you need is the window Handle, see if LabVIEW exposes that for you, otherwise we will have to look for an alternative way of retrieving it.

private static IntPtr _handle = IntPtr.Zero;        static void MyThread()        {            Control testForm = Control.FromHandle(_handle);            testForm.Move += testForm_Move;        }        static void testForm_Move(object sender, EventArgs e)        {            Control myControl = (Control) sender;            System.Diagnostics.Debug.WriteLine("Location: " + myControl.Location + ", Size: " + myControl.Size);        }

So what you have to do from LabVIEW is call the .NET 2.0 static method "Control.FromHandle(IntPtr)", and then you have to listen to its "Move" event. (http://zone.ni.com/reference/en-XX/help/37..._hndl_ax_evnts/) Each Move event callback will have a sender parameter which is simply the Control object, and once you cast it to Control you can get that windows properties.

I am attaching a Visual Studio .NET 2005 C# solution with this example. (I do not have LabVIEW installed here but I can do it when I get home)

Link to comment

I made an attempt to use the "Control.FromHandle(IntPtr)" but I don't seem to have the window's handle correct as the function returns a Null control. I did get the RegisterEventCallBack to work(with a button press).

I used the FindWindow API call to get the handler then created a .Net constructor for the IntPtr object using the value from the system call.

I did find this thread, which used a wrapper dll to convert the hWnd(int32) to an IntPtr but that didn't seem to work either. :wacko:

I have included what I have come up with.

Link to comment

This is what I came to conclude:

The int to IntPtr VI works perfectly fine, I verified this by getting the actual handle to my window by using Winspector, and by calling the "ToInt()" function of the resultant IntPtr .NET object.

Now, after calling the Control.FromHandle function, I tried accessing any property of the resultant .NET object (of type Control), and none of the properties were coming back! I fear this may be because of some sort of Security feature of .NET. I will try to replicate this similar behavior on my computer by creating a non-.NET (aka unmanaged) C++ program that would represent LabVIEW, and then call the same .NET functions.

Real quick, what version of .NET are you running?

Another thing we can do is to write our own custom .NET Assembly that would implement the desired behavior and to then call our own custom .NET Assembly to do what we want.

Link to comment

ok, i just read on this page: http://www.dotnet247.com/247reference/msgs/57/285549.aspx

that Control.FromHandle only works on windows in the current process (for .NET). Now the .NET code that you call should be running in a different process than your LabVIEW process, so Windows Security finally takes effect.... I guess we may have to do this the old-fashioned way - with windows hooks.

I will have to do some reading first for this one. My app had all its windows running in the same process, but apparently that is not the case for LabVIEW.

Take a look at this NI example:

http://zone.ni.com/devzone/cda/epd/p/id/4394

You want to intercept messages that go into your LabVIEW window, and you want to listen for the WM_MOVE message. (Too bad we can't do this in .NET)

anyway, have to go get some food now.

Link to comment

Hmmm....

Well that example seems to work, except it doesn't catch all the messages or, at least, not the ones I was looking for. The only messages I can get are the mouse move and keyboard events. I have an idea on how to use what messages I can access.

I can get the WM_NCLBUTTONDOWN and check if the event occurred in the title bar. Then look for WM_MOUSEMOVE events to see if the mouse moves(ie: moving the window), and also check for WM_NCMOUSEMOVE to see if the button is released. I can't seem to capture the WM_NCLBUTTONUP event.

I working on a mock up example of what I have come up with and will post it later.

Link to comment
  • 4 months later...

QUOTE (rpodsim @ Jan 29 2009, 10:54 PM)

... except it doesn't catch all the messages or, at least, not the ones I was looking for.

Does someone fixed that prob? I tried to catch the WM_MOVING message but I cant receive it. I've tried something like that:

#include "stdafx.h"#include "extcode.h"</P> <P>HHOOK hWndProc;</P> <P>BOOL APIENTRY DllMain( HMODULE hModule,					   DWORD  ul_reason_for_call,					   LPVOID lpReserved	  ){switch (ul_reason_for_call){case DLL_PROCESS_ATTACH: hWndProc = NULL; break;  case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH: if(hWndProc != NULL)  UnhookWindowsHookEx(hWndProc); break;}return TRUE;}</P> <P>// Prototypesextern "C" __declspec(dllexport) int CatchWindowMessage(LVRefNum *ptargetWnd);LRESULT WINAPI WndProc(int nCode, WPARAM wParam, LPARAM lParam);</P> <P>extern "C" __declspec(dllexport) int CatchWindowMessage(LVRefNum *ptargetWnd){ HWND LVhWnd = (HWND)(*ptargetWnd); DWORD targetThread = GetWindowThreadProcessId(LVhWnd, NULL); hWndProc = SetWindowsHookEx(WH_GETMESSAGE, &WndProc, NULL, targetThread); return 0;}</P> <P>/****************************************************************   WH_GETMESSAGE hook procedure  ****************************************************************/ </P> <P>LRESULT WINAPI WndProc(int nCode, WPARAM wParam, LPARAM lParam) {MSG *msg = (MSG*)lParam;</P> <P>if (nCode < 0)  // do not process message 	   return CallNextHookEx(hWndProc, nCode, wParam, lParam);  switch (nCode) { case HC_ACTION:switch(msg->message){case WM_MOVING:MessageBox(NULL, "Wnd moving", "WM Info", MB_OK);</P> <P>   default:break;}  return CallNextHookEx(hWndProc, nCode, wParam, lParam); }

Unfortunately I can't catch WM_MOWING like I tried to do.

Best regards and sorry about my english.

Link to comment
  • 4 months later...

I believe there is a MS Windows system call that you can make to tell the OS to lock two windows together. My memory says that I've heard another LV programmer use such a technique, but I know nothing more than that. If you're on non-MSWin systems, you might see if that OS has such a function.

The Windows API call that you are thinking of is SetParent. I have used it in an application, and it works with LabVIEW panels. You just need to get the handles of the parent and child VI's.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.