What is the default WindowProc of a list-view control? - c

What is the default WindowProc of a list-view control before I change it using SetWindowLong()?

That's determined by the system when it registers the window class. It is presumably implemented in comctl32.
There's nothing special about one of the built-in window classes in this regard. Just as is the case for a user defined class, the default window proc is whatever was specified when the class was registered.

to get the wndproc for a window class use GetClassLongPtr with nIndex=GCLP_WNDPROC, also you can use SetClassLongPtr to super class the window.

Related

Dialog appears behind other windows

I'm using the Prism dialog service to create an unhandled exception dialog. I have a splash screen window that, while it doesn't have the TopMost property set (tried that and it was totally miserable :), I use Activate on it to get it to rise to the top so it appears over the main window as it loads up.
The problem is when an exception is thrown and the unhandled exception dialog that I made pops up, it appears behind the splash screen, leaving the user wondering what happened until they notice an extra button in the task bar.
The dialog is a UserControl, as instructed by the documentation, and it has no Activate function. And when I try to get a handle to the parent window in the constructor, the Parent property is null.
How can I bring a dialog to the top of other windows?
Prism's dialog service sets the Owner of a dialog automatically to the first active Window that is found in the Application.Current.Windows collection if the dialog window does not already have set an owner. It does not expose any methods to access or activate windows directly. In an MVVM service you would not do that.
In Prism <= 7.x, you can only have a single dialog window host. By default this is a regular Window. You have to share this dialog host window type for all of your dialogs, so setting a different Owner in a custom Window is not an option. Since Owner is null when a Window is instantiated, its owner will be the first active window.
This behavior is problematic if you want the Owner of your dialog to be a different window like your splash screen, so it appears on top of it automatically or modally or have no owner at all.
You cannot activate the dialog in the constructor of your UserControl, as it cannot be set as the Content of the parent dialog host Window before it is instantiated. You either have to use the Application.Current.Windows collection to find the dialog or create a custom dialog service for now for both activating or setting an Owner.
Application Windows
If you want to find the dialog host window in Application.Current.Windows, you can filter this collection after showing the dialog and check the Content of each window, one will contain your UserControl type. If you only show the unhandled exception dialog once, there will be a single window instance with this UserControl. If you show it multiple times, you could identify the current instance via a property on its view model accessible by DataContext that you have set before by passing a DialogParameter in Show. Consider creating a service.
Custom Dialog Service
Personally, I prefer creating a custom dialog service, as it gives you more control over what you are doing. To create a custom interface that exposes the methods of the built-in IDialogService, as well as your own methods, depeding on your requirements.
public interface ICustomDialogService : IDialogService
{
public void ShowOrphan(string name, IDialogParameters parameters, Action<IDialogResult> callback);
}
I simply create a new method ShowOrphan to show a dialog that has no owner and is activated automatically when shown, so it is in the foreground. Adapt it to your requirements, like passing in an explicit owner or just an owner type, so that the dialog service searches an instance in the application window collection itself.
Next, implement the ICustomDialogService in a CustomDialogService type. You can just copy the code from the public repository. Be sure to use the code for your version of Prism, see Tags.
You do not have to change much. Just pass appropriate parameters from your new public method down the ConfigureDialogWindowProperties method, which is responsible for setting the window owner. If activating the dialog window is really necessary apart from showing it, you can do that in ShowDialogInternal.
public class CustomDialogService : ICustomDialogService
{
// ...other public members.
public void ShowOrphan(string name, IDialogParameters parameters, Action<IDialogResult> callback)
{
// Appended a new parameter "isOrphan"
ShowDialogInternal(name, parameters, callback, false, true);
}
// ...other private members.
// Appended a new parameter "isOrphan"
void ConfigureDialogWindowProperties(IDialogWindow window, FrameworkElement dialogContent, IDialogAware viewModel, bool isOrphan)
{
// ...other code.
if (isOrphan)
return;
if (window.Owner == null)
window.Owner = System.Windows.Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.IsActive);
}
}
If you are done, you have to overwrite the registration for the old dialog service.
containerRegistry.RegisterSingleton <CustomDialogService>();
containerRegistry.Register<IDialogService, CustomDialogService>();
containerRegistry.Register<ICustomDialogService, CustomDialogService>();
Now you can resolve the ICustomDialogService and use its ShowOrphan method to show the window.

How to get the old value of a TrackBar without a custom control or separate field?

I am trying to get the old Value of a TrackBar when the Scroll event gets raised. I could do this by creating a separate field and storing that value whenever it changes, or overriding the event in a custom control however, I am already using the built-in TrackBar and I'd prefer to not have to redesign my forms.
The Microsoft documentation does not seem to have any information on this and the EventArgs parameter on the OnScroll and OnValueChanged methods seem pretty generic.
Is there a way to achieve this and how?
Sources:
Microsoft Documentation: TrackBar.OnScroll Method
Microsoft Documentation: TrackBar.Scroll Event
How to override method and event in WinForm UserControl in C#?
Microsoft Documentation: TrackBar.ValueChanged Event
Microsoft Documentation: TrackBar.Value Property
Microsoft Documentation: TrackBar.OnValueChanged Method
I believe there isn't a built-in way to achieve what you're looking for.
To address your concern about having to replace all the TrackBar controls on a form with the derived custom control, here's how I usually do it:
Create your control class which inherits the TrackBar control.
Open your FormName.Designer.cs or FormName.Designer.vb file.
Click Ctrl+H to open the "Find and replace" window.
Enter System.Windows.Forms.TrackBar in the "Find" field, and YourNameSpace.CustomTrackBar in the "Replace with" field.
Click "Replace all" (You can do it one by one if you're afraid to mess something up).
Rebuild your project.
Hope that helps.

WPF+Unity: UserControl with usage of services?

I've an UserControl, which basically looks like this:
You guessed, the goal is to allow the user to choose a file/folder when clicking on Browseand then display the file path in the TextBox.
I started my first fully MVVM application(Using Prism+Unity), and I have in fact an IDialogService which allows me to show a MessageBox, but also display some OpenFileDialog and SaveFileDialog.
I would like to use the implementation provided for this IDialogService in order to display to the user my dialog box once the Browse command is executed.
Since the UserControl isn't built with Unity, how to request the implementation ?
If I understand you correctly, your UserControl needs to get hold of the Unity container you're using, one way or another. If you're instantiating the UserControl yourself, you can consider adding it as a constructor parameter; if it's instantiated by the framework you could consider a Container property or a setter method. Or you could go with the container as a singleton.
Either way, assuming your UserControl has a field like so...
IUnityContainer container;
...and that you've managed to point it to the container you're using, you should be able to resolve your service the normal way:
IDialogService service = container.Resolve<IDialogService>();
service.OpenFileDialog(...);

User control, custom control, inheritance and override

I know this question is probably going to get alot of "Duplicate question" comments but i have yet to see one with an answer that works or isn't simply "Avoid it at all cost". But here goes, i have created a control lets call it "ControlA" in a project called "ControlA_Project" and i was intending to override some of its virtual methods in a control called "ControlB" that inherites "ControlA" in another project called "ControlB_Project" . The idea being that "ControlA" has save and load methods that i wish to change from saving and loading to file, too saving and loading to database ( and if later on another save and load type is required i can just override those methods again ).
The problem i have is i originally had "ControlA" as a usercontrol and when i tried adding the new control with the overrides ("ControlB") into a window i would get this error:
The component 'ControlB_Project.ControlB' does not have a resource identified by the URI '/ControlA_Project;component/usercontrols/ControlA.xaml'.
Googling the error i came to the conclusion you could not inherit from a user control ( or for the sake of arguement it wasn't a good idea ). So i then changed the control from a user control to a custom control. this however then leads me to another problem, a template for a control doesnt link to the code behind (i.e On_Click) like it does in a user control and there is no easy way to simply override the behavier (as far as i am aware). I know i can retemplate ControlB by copy and pasting ControlAs template and changing a few lines but controlA has a large template as it is and making mutliple copies seems a waste of space.
So put simply is there a correct way to change the behavier of a control in wpf?
First, remember that the ControlTemplate can be changed by the user alot so you need to make sure that important fields are clearly marked.
So if you want an OnClick event. First mark your button as "important"
<Button x:Name="PART_MyButton"/>
Its also a good idea to mark this aswell on your control class
[TemplatePart(Name = "PART_MyButton", Type = typeof(Button))]
public class MyCustomControl : Control
Now you want to attach to the on click event of that button to do that, override the OnApplyTemplate method.
public override void OnApplyTemplate()
{
mButton = Template.FindName("PART_MyButton", this) as Button;
mButton.Click += MyEventHandler;
}
Depending on how well your control can work without the control, you should gracefully handle a not found control or throw an exception.
One final thing is. If you override a control which has a default style, it might be a good idea to provide a new default style.
static MyCustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
and placing an implicit style in your generic.xaml

WPF Visibility based upon global variable value

I have a boolean global variable that is set true if an administrator is logged in and wants to amend the content of the lists and comboboxes. As a result, a button is displayed beside each combo to display a dialog box when clicked.
If I was not coding for WPF, I would probably include some sort of code similar to the following in each Window:
If gAdminEditLists=True Then btnUpdateCombo.Visibility=Visible Else btnUpdateCombo.Visibility=Collapsed
In my WPF app, I am using a style for the button that is used throughout the application and I am guessing that the best way forward is to set the Visibility of the button within the style based upon the value of the gAdminEditLists variable.
The only way I can see of doing this is to use some sort of converter within the button style that converts the gAdminEditLists value to visible or collapsed.
I'm not too sure how to proceed with this or whether this is the best approach, so any suggestions would be appreciated.
well your problem is that you're using a global variable isn't it?
if you had a property that implemented notification or a dependency property you would be ok. the closest thing to a global variable is a property on the app ( i assume thats where your global is )
defining dependency properties on app.xaml, however you could just use INotifyPropertyChanged.
binding to properties in app.xaml.cs
enjoy!
Have a look at the BooleanToVisibilityConverter class in the System.Windows.Controls namespace.

Resources