How to wire up to events associated with VS2010's Outlining model - visual-studio-2010

I'm writing an extension for VS2010 that reorders a page of code by rearranging code sections and inserting #regions.
I want to be able to code in a call to the "Edit.CollapseToDefinitions" command after I've completed my text manipulations. I can invoke this command in the Visual Studio model by calling ExecuteCommand on my DTE2 object.
However, if I invoke the command immediately after moving my text around the document VS hasn't had time to update its outlining record. So, I want to be able to hook up to outlining events on the current Text Editor window. Does anyone know how to do this?

There's no great way to do it. You can listen for outlining region change events on the IOutliningManager (retrieved by [Import]ing an IOutliningManagerService), but there are no guarantees that the first event will be the one in which the language service re-introduces all the outlining regions it can. Most languages do it on the VS idle loop, but still at some delay so that it doesn't interrupt slow typing.
I would try playing around with something like:
Complete your text edits
Call collapse to definitions
Subscribe to IOutliningManager.RegionsChanged
If the next event is raised in, say, the next 5 seconds, call collapse to definitions again.

Related

Implementing a Custom Cocoa Event Tracking Loop

I'm working on a custom cross platform UI library that needs a synchronous "ShowPopup" method that shows a popup, runs an event loop until it's finished and automatically cancels when clicking outside the popup or pressing escape. Keyboard, mouse and scroll wheel events need to be dispatched to the popup but other events (paint, draw, timers etc...) need to be dispatched to their regular targets while the loop runs.
Edit: for clarification, by popup, I mean this kind of menu style popup window, not an alert/dialog etc...
On Windows I've implemented this fairly simply by calling GetMessage/DispatchMessage and filtering and dispatching messages as appropriate. Works fine.
I've much less experience with Cocoa/OS X however and finding the whole event loop/dispatch paradigm a bit confusing. I've seen the following article which explains how to implement a mouse tracking loop which is very similar to what I need:
http://stpeterandpaul.ca/tiger/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/chapter_5_section_4.html
but... there's some things about this that concern me.
The linked article states: "the application’s main thread is unable to process any other requests during an event-tracking loop and timers might not fire". Might not? Why not, when not, how to make sure they do?
The docs for nextEventMatchingMask:untilDate:inMode:dequeue: states "events that do not match one of the specified event types are left in the queue.". That seems a little odd. Does this mean that if an event loop only asks for mouse events then any pressed keys will be processed once the loop finishes? That'd be weird.
Is it possible to peek at a message in the event queue without removing it. eg: the Windows version of my library uses this to close the popup when it's clicked outside, but leaves the click event in the queue so that clicking outside the popup on a another button doesn't require a second click.
I've read and re-read about run loop modes but still don't really get it. A good explanation of what these are for would be great.
Are there any other good examples of implementing an event loop for a popup. Even better would be pseudo-code for what the built in NSApplication run loop does.
Another way of putting all this... what's the Cocoa equivalent of Windows' PeekMessage(..., PM_REMOVE), PeekMessage(..., PM_NOREMOVE) and DispatchMessage().
Any help greatly appreciated.
What exactly is a "popup" as you're using the term? That term means different things in different GUI APIs. Is it just a modal dialog window?
Update for edits to question:
It seems you just want to implement a custom menu. Apple provides a sample project, CustomMenus, which illustrates that technique. It's a companion to one of the WWDC 2010 session videos, Session 145, "Key Event Handling in Cocoa Applications".
Depending on exactly what you need to achieve, you might want to use an NSAlert. Alternatively, you can use a custom window and just run it modally using the -runModalForWindow: method of NSApplication.
To meet your requirement of ending the modal session when the user clicks outside of the window, you could use a local event monitor. There's even an example of just such functionality in the (modern, current) Cocoa Event Handling Guide: Monitoring Events.
All of that said, here are (hopefully no longer relevant) answers to your specific questions:
The linked article states: "the application’s main thread is unable to process any other requests during an event-tracking loop and
timers might not fire". Might not? Why not, when not, how to make
sure they do?
Because timers are scheduled in a particular run loop mode or set of modes. See the answer to question 4, below. You would typically use the event-tracking mode when running an event-tracking loop, so timers which are not scheduled in that mode will not run.
You could use the default mode for your event-tracking loop, but it really isn't a good idea. It might cause unexpected re-entrancy.
Assuming your pop-up is similar to a modal window, you should probably use NSModalPanelRunLoopMode.
The docs for nextEventMatchingMask:untilDate:inMode:dequeue:
states "events that do not match one of the specified event types are
left in the queue.". That seems a little odd. Does this mean that if
an event loop only asks for mouse events then any pressed keys will be
processed once the loop finishes? That'd be weird.
Yes, that's what it means. It's up to you to prevent that weird outcome. If you were to read a version of the Cocoa Event Handling Guide from this decade, you'd find there's a section on how to deal with this. ;-P
Is it possible to peek at a message in the event queue without removing it. eg: the Windows version of my library uses this to close
the popup when it's clicked outside, but leaves the click event in the
queue so that clicking outside the popup on a another button doesn't
require a second click.
Yes. Did you notice the "dequeue:" parameter of nextEventMatchingMask:untilDate:inMode:dequeue:? If you pass NO for that, then the event is left in the queue.
I've read and re-read about run loop modes but still don't really get it. A good explanation of what these are for would be great.
It's hard to know what to tell you without knowing what you're confused about and how the Apple guide failed you.
Are you familiar with handling multiple asynchronous communication channels using a loop around select(), poll(), epoll(), or kevent()? It's kind of like that, but a bit more automated. Not only do you build a data structure which lists the input sources you want to monitor and what specific events on those input sources you're interested in, but each input source also has a callback associated with it. Running the run loop is like calling one of the above functions to wait for input but also, when input arrives, calling the callback associated with the source to handle that input. You can run a single turn of that loop, run it until a specific time, or even run it indefinitely.
With run loops, the input sources can be organized into sets. The sets are called "modes" and identified by name (i.e. a string). When you run a run loop, you specify which set of input sources it should monitor by specifying which mode it should run in. The other input sources are still known to the run loop, but just ignored temporarily.
The -nextEventMatchingMask:untilDate:inMode:dequeue: method is, more or less, running the thread's run loop internally. In addition to whatever input sources were already present in the run loop, it temporarily adds an input source to monitor events from the windowing system, including mouse and key events.
Are there any other good examples of implementing an event loop for a popup. Even better would be pseudo-code for what the built in
NSApplication run loop does.
There's old Apple sample code, which is actually their implementation of GLUT. It provides a subclass of NSApplication and overrides the -run method. When you strip away some stuff that's only relevant for application start-up or GLUT, it's pretty simple. It's just a loop around -nextEventMatchingMask:... and -sendEvent:.

How to break code on a click event?

I have this application that I need to disassemble. I don't have a clue on how to stop the running code on the desired location, so I decided my best guess would be breaking upon a button click. But how do I capture button clicks? I know it has probably something to do with the Windows functions such as CallNextHookEx. I'm using IDA PRO to disassembly.
IDA PRO is used mostly as disassembler, for static analysis purposes. I'd suggest you to use Ollydbg (or some other debugger, if you want to) because it will suit better to debugging purposes.
I don't know if you can set a breakpoint on an API like that.
But you can do this:
Load the application in olly, or attach to it.
Generate the event by clicking on anything.
Stop the application from ollydbg(F12)
Use C(k)all stack(ALT+K)
You will see a few calls to functions, one of them is doing what you need. But you may need to go to upper calls to see the whole loop. So you will just try which one it is. There will be a loop in one of them.That loop will have conditional jumps and generate events, load forms, fill the app etc. And when you place a breakpoint on the right jump there, it will stop at each mouse click.
When I'm debugging apps, most of the times I find myself on a breakpoint like this, and I see from the beginning how the application is filling an empty form(it takes so long.)

How to tell if user control is done loading in vb6

How can you tell if a VB6 user control is done loading? Is there a custom UserControl_Loaded event or something?
What do you mean by loading? A UserControl has an Initialize event which you should use to set initial values. VB itself will then load in property values. In any of the other events you can assume the control is set up and ready to go.
You can read about the order of events a UserControl goes through here: https://msdn.microsoft.com/en-us/library/aa242140%28v=vs.60%29.aspx
I tend to put "load" logic into the InitProperties and ReadProperties event handlers. The first one gets called when a UserControl instance is added to a container (Form, another UserControl) within the IDE. The second one gets called on all subsequent "creations" within the IDE and at run time.
You can check Ambient.UserMode to determine whether a subsequent creation's ReadProperties event is due to editing operations vs. an IDE or compiled run.
Initialize events always occur, and before the other two. At that time Ambient and other context objects are not available yet.
See that fine manual: Understanding Control Lifetime and Key Events

Visual Studio 2010 status bar in C++/CLI

In VS 2010 I'm trying to read a text file on button click and set that value as the status button value. The text file will always contain a single line with a number between 0 and 100. I'm trying to do this in C++/CLI because I'm familiar with C++ but this seems like a whole different lang! This is what I have but it causes the GUI to crash. I know it's the loops fault but I don't know why, what's the best (noob) way to approach this?
while (result<100)
{
StreamReader ^read=gcnew StreamReader("Status.txt");
String ^x=read->ReadLine();
read->Close();
Int32::TryParse(x, result);
progressBar1->Value= result;
}
You haven't said whether you're using WPF or WinForms for your GUI, but this answer applies equally to either.
If your while loop in in a button handler, that code is running on the UI thread. The UI thread is also responsible for redrawing the GUI. Since your button method isn't returning, it's never getting to the 'repaint' code, and the UI just stops.
You didn't mention what is writing those integers 0 to 100 to a file. If it's another thread in the same application, there are MUCH better ways of communicating the progress between threads.
I recommend that you replace that while loop with a Timer object of some sort. (There are appropriate classes, depending on whether you're using WPF or WinForms.) Set the interval to something like 500 milliseconds, start the timer when your background task begins, and stop the timer when it ends. In the timer method, don't have a while loop, just do it once.

Which Windows API controls filename editing?

When you press F2 to edit a filename in Windows Shell, there is a limited set of editing keys that is understood - e.g. CTRL+Arrow Keys, Home, End, CTRL+X. For example, when you type CTRL+Right Arrow, the cursor will stop right after a dash, but will not stop at a period. Are these actions customizable, and if so, how?
Any additional information not directly related but which you feel might help the topic will also be appreciated.
You can set a custom word-break procedure for your edit control using EM_SETWORDBREAKPROC; EditWordBreakProc is the corresponding callback function that the OS calls when it needs to find where a word break occurs.
From the docs:
Either a multiline or a single-line edit control might call this function when the user presses arrow keys in combination with the CTRL key to move the caret to the next word or previous word.
The key combinations themselves are not directly customizable, and for a good reason -- so that the user experience is uniform across all applications. Of course, you could subclass the edit control and handle keyboard messages yourself but I guess that's not the point here.
The Windows version matters, but in general this behavior is baked into SysListView32, the native list view control. No, keyboard handling is hard-baked. Subclassing the control is technically possible, just not practical since it lives inside Explorer.exe. And having no clue where the caret is located inside the label, there are no messages for it.
By "Windows Shell" I assume you mean Windows Explorer, but the answer is likely the same no matter what program you are talking about.
Explorer simply creates an EDIT control and moves it into position. The editing behavior comes from this stock system control, plus whatever additional logic Explorer adds to its own instance of it.
While you can easily alter the behavior of an EDIT control that belongs to a thread in your own process, doing so in another process requires a global hook. We will stipulate that you understand the amount of work involved in doing a global hook correctly, and which will function in both x86 and x64 environments.
You cannot directly interfere with the behavior of an EDIT control in another process with WH_CALLWNDPROC, but you can use WH_CALLWNDPROCRET to observe keyboard messages, check that the window is and EDIT control, check that the EDIT control belongs to Explorer, and then knowing precicesly how the EDIT control responded to that keyboard event, do something additional like backing up to that period.
Or maybe you could use a WH_CBT hook to monitor HCBT_CREATEWND and subclass the EDIT control each time it gets created.
The effort is probably not worth the benefit.

Resources