I would like to use this menu through C# or F# in Win7. I even couldn't find how to call it.
In Introducing The Taskbar APIs on the MSDN magazine, it describes about how to use the Thumbnail Toolbars.
The managed equivalent does not currently appear in the Windows API
Code Pack, but it is planned to appear in a future release. In the
meantime, you can use the Windows 7 taskbar Interop Sample Library. It
contains the ThumbButtonManager class with the corresponding
CreateThumbButton and AddThumbButtons methods for controlling the
thumbnail toolbar, and also the ThumbButton class for modifying the
thumbnail button state at runtime. To receive notifications, you
register for the ThumbButton.Clicked event and override your window
procedure to dispatch the messages to the ThumbButtonManager class,
which does the dispatching magic for you. (For more details, see the
blog article Windows 7 Taskbar: Thumbnail Toolbars.)
ITaskbarList3* ptl;//Created earlier //In your window procedure:
switch (msg) {
case g_wmTBC://TaskbarButtonCreated
THUMBBUTTON buttons[2]; buttons[0].dwMask = THB_ICON|THB_TOOLTIP|THB_FLAGS; buttons[0].iId = 0;
buttons[0].hIcon = GetIconForButton(0); wcscpy(buttons[0].szTip, L"Tooltip 1"); buttons[0].dwFlags = THBF_ENABLED;
buttons[1].dwMask = THB_ICON|THB_TOOLTIP|THB_FLAGS;
buttons[1].iId = 1; buttons[1].hIcon = GetIconForButton(1);
wcscpy(buttons[0].szTip, L"Tooltip 2"); buttons[1].dwFlags = THBF_ENABLED; VERIFY(ptl->ThumbBarAddButtons(hWnd, 2,buttons));
break;
case WM_COMMAND:
if (HIWORD(wParam) == THBN_CLICKED) {
if (LOWORD(wParam) == 0)
MessageBox(L"Button 0 clicked", ...);
if (LOWORD(wParam) == 1) MessageBox(L"Button 1 clicked", ...);
}
break;
.
.
And in the second link it shows a C# sample using a wrapper library:
As always, the managed wrappers come to the rescue. The
ThumbButtonManager class (in the Windows7.DesktopIntegration project)
_thumbButtonManager = this.CreateThumbButtonManager();
ThumbButton button2 = _thumbButtonManager.CreateThumbButton(102, SystemIcons.Exclamation, "Beware of me!");
button2.Clicked += delegate
{
statusLabel.Text = "Second button clicked";
button2.Enabled = false;
};
ThumbButton button = _thumbButtonManager.CreateThumbButton(101, SystemIcons.Information, "Click me");
button.Clicked += delegate
{
statusLabel.Text = "First button clicked";
button2.Enabled = true;
};
_thumbButtonManager.AddThumbButtons(button, button2);
Note that you have tooltips and icons at your disposal to personalize the thumbnail toolbar to your application’s needs. All you need to do now is override your windows’ window procedure and call the DispatchMessage method of the ThumbButtonManager, so that it can correctly route the event to your registered event handlers (and of course, don’t forget to call the default window procedure when you’re done!):
if (_thumbButtonManager != null)
_thumbButtonManager.DispatchMessage(ref m);
base.WndProc(ref m);
Related
As we know, if we press the F8(Play) keyboard button, iTunes or Music .app opened in default on macOS. Some Swift classes are available for preventing this keyboard shortcut but they are not compatible with C# & Xamarin. Fore example, Spotify macOS app have this ability. If you press play button on UI once, it takes the control over iTunes and handles the "Play" button key event.
I have this code block. However, macOS cannot fires the code block because of iTunes. The other keys like letters and numbers working correctly:
private NSEvent KeyboardEventHandler(NSEvent theEvent)
{
ushort keyCode = theEvent.KeyCode;
if(keyCode== 100) //rbKeyF8 100 is play button.
{
switch (isplaying)
{
case true:
StopMusic();
break;
case false:
PlayMusic();
break;
}
}
// NSAlert a = new NSAlert()
//{
// AlertStyle = NSAlertStyle.Informational,
// InformativeText = "You press the " + keyCode + " button :)",
// MessageText = "Hi"
//};
//a.RunModal();
return theEvent;
}
How can we do it with C# ? Thanks.
Answer is:
Register a new subclass
[Register ("App")]
public class App : NSApplication
{
public App (System.IntPtr p) : base (p)
{
}
public override void SendEvent (NSEvent theEvent)
{
base.SendEvent (theEvent);
}
}
In Info.plist change the PrincipalClass
<key>NSPrincipalClass</key>
<string>App</string>
And need to subclass NSApplication and look at sendEvent. You should convert Swift code to C#. Related swift code is here:
Make my Cocoa app respond to the keyboard play/pause key?
Now, i have another problem. Yep, this code block solved my problem’s
first part. Now my app responds the play button press. However, iTunes
opened after the my app's respond. How can I prevent it to open ?
VS now comes with an interactive window, but unlike running the raw CSI.EXE Roslyn process, Visual Studio adds IntelliSense and a few other features such as being able to load in the current project.
I want to write a VS plug-in that tracks all text editor changes in this window. Is this possible? What I'm looking for is something akin to PreviewKeyDown/PreviewTextInput WPF events. Can I get those on the C# interactive window and, if so, how?
Here's how far I got so far:
var dte = Shell.Instance.GetComponent<DTE>();
foreach (Window window in dte.MainWindow.Collection)
{
if (window.Kind.ToUpper().Contains("TOOL"))
{
if (window.Caption == "C# Interactive")
{
WpfWindow wpfWindow = (WpfWindow)HwndSource.FromHwnd((IntPtr) window.HWnd).RootVisual;
for (int i = 0; i < VTH.GetChildrenCount(wpfWindow); ++i)
{
// now what?
}
}
}
}
Here is some code that will get an IWpfTextViewHost reference on the C# interactive Window. From there, you can have access to all text services from Visual Studio: Text lines, Text buffer, etc. (or you can hook directly on WPF's controls, which I don't recommend)
// get global UI shell service from a service provider
var shell = (IVsUIShell)ServiceProvider.GetService(typeof(SVsUIShell));
// try to find the C# interactive Window frame from it's package Id
// with different Guids, it could also work for other interactive Windows (F#, VB, etc.)
var CSharpVsInteractiveWindowPackageId = new Guid("{ca8cc5c7-0231-406a-95cd-aa5ed6ac0190}");
// you can use a flag here to force open it
var flags = __VSFINDTOOLWIN.FTW_fFindFirst;
shell.FindToolWindow((uint)flags, ref CSharpVsInteractiveWindowPackageId, out IVsWindowFrame frame);
// available?
if (frame != null)
{
// get its view (it's a WindowPane)
frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocView, out object dv);
// this pane implements IVsInteractiveWindow (you need to add the Microsoft.VisualStudio.VsInteractiveWindow nuget package)
var iw = (IVsInteractiveWindow)dv;
// now get the wpf view host
// using an extension method from Microsoft.VisualStudio.VsInteractiveWindowExtensions class
IWpfTextViewHost host = iw.InteractiveWindow.GetTextViewHost();
// you can get lines with this
var lines = host.TextView.TextViewLines;
// and subscribe to events in text with this
host.TextView.TextBuffer.Changed += TextBuffer_Changed;
}
private void TextBuffer_Changed(object sender, TextContentChangedEventArgs e)
{
// text has changed
}
Note "Microsoft.VisualStudio.VsInteractiveWindow" assembly is not specifically documented but the source is open: http://sourceroslyn.io/#Microsoft.VisualStudio.VsInteractiveWindow
I want to develop a music app for Windows 10 and I'm curious about the interface provided by Groove Music next to the volume bar. I've tried Googling to get more information about it but I haven't had any success whatsoever. When I'm playing music in Groove Music and I raise or lower the volume, the name as well as the artist and album artwork of the current song show up with music controls next to the volume indicator this:
I was wondering how I could create this dialog in my own app and what windows API's I'd have to look into.
I'm going to add my input to this even though there is a great answer already by #Stamos, because I've found that it is actually possible to use SystemMediaTransportControls from a native windows app (not only a universal app).
First thing, it does still require a reference to the universal winmd files, so it will only work on Win10. They will be located in the 10 sdk, and you can add them via the regular Add Reference -> Browse but you may need to change the filter on the bottom right of the dialog to "All Files" for them to show up. They are found here on my PC:
Windows.Foundation.UniversalApiContract: C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\1.0.0.0\Windows.Foundation.UniversalApiContract.winmd
Windows.Foundation.FoundationContract: C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\2.0.0.0\Windows.Foundation.FoundationContract.winmd
After you have the necessary references, you'll run into another problem - you can't access the transport controls via the usual SystemMediaTransportControls.GetForCurrentView(); (it will throw an exception) because you don't actually have a universal view. This is alleviated by using the following:
SystemMediaTransportControls systemControls =
BackgroundMediaPlayer.Current.SystemMediaTransportControls;
After this, feel free to use any of the samples online or Stamos' answer.
You need to use SystemMediaTransportControls
Here is a basic setup with Play and Pause. If you like to enable more controls you can do using the available properties for ex.
systemControls.IsNextEnabled = true;
and you have to add the case in the button switch.
case SystemMediaTransportControlsButton.Next:
//handle next song
break;
xaml
<MediaElement x:Name="mediaElement" Height="100" Width="100" AreTransportControlsEnabled="True"/>
C#
public MainPage()
{
this.InitializeComponent();
systemControls = SystemMediaTransportControls.GetForCurrentView();
// Register to handle the following system transpot control buttons.
systemControls.ButtonPressed += SystemControls_ButtonPressed;
mediaElement.CurrentStateChanged += MediaElement_CurrentStateChanged;
systemControls.IsPlayEnabled = true;
systemControls.IsPauseEnabled = true;
}
private void MediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
switch (mediaElement.CurrentState)
{
case MediaElementState.Playing:
systemControls.PlaybackStatus = MediaPlaybackStatus.Playing;
break;
case MediaElementState.Paused:
systemControls.PlaybackStatus = MediaPlaybackStatus.Paused;
break;
case MediaElementState.Stopped:
systemControls.PlaybackStatus = MediaPlaybackStatus.Stopped;
break;
case MediaElementState.Closed:
systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
break;
default:
break;
}
}
void SystemControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
PlayMedia();
break;
case SystemMediaTransportControlsButton.Pause:
PauseMedia();
break;
case SystemMediaTransportControlsButton.Stop:
StopMedia();
break;
default:
break;
}
}
private async void StopMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement.Stop();
});
}
async void PlayMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (mediaElement.CurrentState == MediaElementState.Playing)
mediaElement.Pause();
else
mediaElement.Play();
});
}
async void PauseMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement.Pause();
});
}
Output
Also if you want all this to work in background you will have to do a Declaration in Package.appxmanifest for a Background Tasks, enable audio and add an entry point like TestUWP.MainPage
<MediaElement x:Name="Media"
AreTransportControlsEnabled="True">
<MediaElement.TransportControls>
<MediaTransportControls
Style="{StaticResource MediaTCStyle}"/>
</MediaElement.TransportControls>
</MediaElement>
The style is quite big so i'm attaching a link
MediaTransportControls styles and templates
I got the style from the article(link above) and modified it in my own ResourceDictionary.
EDIT: I see I'm getting a lot of downvotes on this post. I've tried to explain what I try to do, where my errors and in which direction want to go. I'm asking for insight in what I'm doing wrong. If you downvote; pleas tell me why, so I can improve the question. Thanks.
I'm creating an application where I have one main form, and several different User Controls which the user works on. This helps me splitting the code, managing the different parts of the program. And it would be easy to expand the application later on.
I'm trying to create a class where I manage the active controls I want to call one function in that class with as argument the form that should become active.
An image can illustrate how I try to setup this application. Note that the control manager class is not a seperate class in the code i show below, but a partial class of the mainform. Any tips on how to get it like in the image are very welcome :)
The class to manage all active forms looks like this: Please note that all user controls are just a user control with some buttons/textboxes etc on it. No code is added at all yet.
public partial class STP2Main
{
// I make each UserControl accessable for the whole class
SetupDeviceControl.SetupDevice SetupDev = new SetupDeviceControl.SetupDevice();
GenConfigFileControl.GenConfigFileControl GenConfFile = new GenConfigFileControl.GenConfigFileControl();
Monitoring.MonitoringControl Monitor = new Monitoring.MonitoringControl();
GenEncKeyControl.GenEncKeyControl GenEncKey = new GenEncKeyControl.GenEncKeyControl();
MenuControl.MenuControl MenuControl = new MenuControl.MenuControl();
public void SelectActiveWindow()
{
// Any active control should be hidden thats what this function does:
HideCurrentActiveControl();
// Check whether the window is already created
if (!WindowExists())
{ // if not created; create the windows:
switch (STP_Design.ProgramParameters.C.NextActiveControl)
{
case STP_Data.Data.SetupDeviceControl: // control 1:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.SetupDeviceControl;
STP_Design.ProgramParameters.C.SetupDeviceControlIsCreated = true;
SetupDev.Parent = this;
SetupDev.Location = new Point(3, 30);
SetupDev.Show();
SetupDev.BringToFront();
break;
case STP_Data.Data.MonitoringControl: //control 2:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MonitoringControl;
STP_Design.ProgramParameters.C.MonitoringControlIsCreated = true;
Monitor.Parent = this;
Monitor.Location = new Point(3, 125);
Monitor.Show();
Monitor.BringToFront();
break;
case STP_Data.Data.MenuControl: // control 3
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MenuControl;
STP_Design.ProgramParameters.C.MenuControlIsCreated = true;
MenuControl.Location = new Point(3, 30);
MenuControl.Parent = this;
MenuControl.Show();
MenuControl.BringToFront();
break;
}
}
else
{ // window is already created so needs to be called to front again:
switch (STP_Design.ProgramParameters.C.NextActiveControl)
{
case STP_Data.Data.SetupDeviceControl:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.SetupDeviceControl;
SetupDev.BringToFront();
break;
case STP_Data.Data.MonitoringControl:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MonitoringControl;
Monitor.Visible = true;
Monitor.BringToFront();
break;
case STP_Data.Data.AdvancedMenu:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.AdvancedMenu;
tabControl1.Visible = true;
tabControl1.BringToFront();
break;
case STP_Data.Data.MenuControl:
STP_Design.ProgramParameters.C.CurrentActiveControl = STP_Data.Data.MenuControl;
MenuControl.Visible = true;
MenuControl.BringToFront();
break;
}
}
btnMenu.BringToFront();
}
// some functions which are called above are not shown; not relevant for this question
}
What I experience is the following: I get no errors at all. But the controls simply not change at all. If I call a window, it is created only once, because I did make it as partial class of my Mainform. (I've tried a complete seperate class, which did result in errors with threading, As I am not an experienced c# programmer, I tried to avoid that using a partial class.)
I'll add another function; which does not do anything at all:
private void HideCurrentActiveControl()
{
switch (STP_Design.ProgramParameters.C.CurrentActiveControl)
{
case STP_Data.Data.SetupDeviceControl:
SetupDev.Visible = false;
break;
case STP_Data.Data.MonitoringControl:
tabControl1.Visible = false;
Monitor.Visible = false;
break;
case STP_Data.Data.GenConfFileControl:
GenConfFile.Visible = false;
break;
case STP_Data.Data.GenEncKeyControl:
GenEncKey.Visible = false;
break;
case STP_Data.Data.MenuControl:
MenuControl.Visible = false;
break;
case STP_Data.Data.AdvancedMenu:
tabControl1.Visible = false;
break;
default:
tabControl1.Visible = false;
break;
}
}
I've tried debugging this part of code and it executes the statements, but I see no changes at all.
I think I've shown what I am trying to do; and how I try to do that. My question is: How do I acces those forms so I can manage them from a seperate class (or in this case partial class of the main form).
Then I have this last function, which does some wierd things. Before I call the SelectActiveWindow() function I update the variable STP_Design.ProgramParameters.C.NextActiveControl to for example: ...AdvancedMenu. (this was before that ...MenuControl) But it does always show that it is still MenuControl. Nowhere in my code is something where I change that value besides right before I start the function. (I've also tried to make the nextcontrol as an argument of the function SelectActiveWindow() but this did the same)
private bool WindowExists()
{
switch (STP_Design.ProgramParameters.C.NextActiveControl)
{
case STP_Data.Data.SetupDeviceControl:
if (STP_Design.ProgramParameters.C.SetupDeviceControlIsCreated)
return true;
else
return false;
case STP_Data.Data.MonitoringControl:
if (STP_Design.ProgramParameters.C.MonitoringControlIsCreated)
return true;
else
return false;
case STP_Data.Data.GenConfFileControl:
if (STP_Design.ProgramParameters.C.GenConfFileIsCreated)
return true;
else
return false;
case STP_Data.Data.GenEncKeyControl:
if (STP_Design.ProgramParameters.C.GenEncKeyControlIsCreated)
return true;
else
return false;
case STP_Data.Data.AdvancedMenu:
return true;
case STP_Data.Data.MenuControl:
if (STP_Design.ProgramParameters.C.MenuControlIsCreated)
return true;
else
return false;
default:
return false;
}
}
Summery of what I am looking for:
I am having a main form where display different user controlls in. I am trying to create a seperate class which is accessable from each control/form in my project. This class should manage the controls which are shown. In the code above I illustrated how I tried to do this, but this does not result in the expected result.
Ok, Now I understand the context needed. We actually do something very similar in my program. Here is a basic outline of how we do it...
Layout
On the main form we have a Panel container that we call pnlMain. It is this control that we add and remove active user controls from. We also have a UserControl object at a global level on the form representing curActiveControl.
Code
When the user selects a window via one of the menu's, we run a function that looks like this
switch (UserSelection)
{
case "Page 1":
if(curActiveControl.GetType() != typeOf(Page1Control))
{
pnlMain.Controls.Remove(curActiveControl);
curActiveControl = new Page1Control();
//do setup and configuration things
pnlMain.Controls.Add(curActiveControl);
}
//do some post processing things
break;
//other pages/specific page controls
}
Refresh();
The downside to this specific method is that the pages themselves are not persistent, so if there are entries or variables you want to have active across a session rather than only while on a page, you have to store them in some other global object and reload them from the user control's Load or Constructor methods.
You could do this same thing but instead of creating a new control instance each time for curActiveControl you could simply replace it with the standby instance of the new control. Be careful with referencing and overwriting though, its not something I personally have tried before.
The key in the method we use is the Panel that holds the user controls. Rather than adjusting the visibility and Z-Order of a large number of user controls, we simply change the displayed control in the main panel and the other control don't even exist at any given point in time.
The other wrinkle is that this functionality is directly on our Main Form. I Don't know how well this will work as another partial class. Its definitely worth a try though.
The following code is from the C# portion of my Android Mono application. It is going to eventually be the GUI for a multimeter simulator, but right now just displays text. It is rather straight forward:
-Click one of the buttons to go to that meter (voltmeter, ammeter, ohmmeter)
-Click the "re-scan" button and a TextView tells you how many times you clicked that button.
-Click one of the other meter buttons or the home button to switch views
That much is working flawlessly. Unfortunately, once I switch views, the buttons cease to work. Below is the code for the Ohm button and the Amp button. The Ohm button is the 'complete' one that brings up views of all of the other screens. For testing purposes, I was going to the amp screen but when I go there, its re-scan button does nothing. None of the buttons do anything.
I am fairly certain that the issue is my use of the delegate commands, but none of my research has led me in any way towards a solution.
I can provide more of the main code and the XML code if needed.
ampButton.Click += delegate
{
SetContentView(Resource.Layout.AmpScreen);
Button ampButtonData = FindViewById<Button>(Resource.Id.CurrentButtonamp);
TextView ampData = FindViewById<TextView>(Resource.Id.ampdata);
ampButtonData.Click += delegate
{
ampData.Text = string.Format("{0} clicks!", count2++);
};
Button amp2volt = FindViewById<Button>(Resource.Id.Amp2VoltButton);
Button amp2ohm = FindViewById<Button>(Resource.Id.Amp2OhmButton);
Button amp2home = FindViewById<Button>(Resource.Id.Amp2HomeButton);
};
ohmButton.Click += delegate
{
SetContentView(Resource.Layout.OhmScreen);
Button ohmButtonData = FindViewById<Button>(Resource.Id.CurrentButtonohm);
TextView ohmData = FindViewById<TextView>(Resource.Id.ohmdata);
ohmButtonData.Click += delegate
{
ohmData.Text = string.Format("{0} clicks!", count3++);
};
Button ohm2amp = FindViewById<Button>(Resource.Id.Ohm2AmpButton);
Button ohm2volt = FindViewById<Button>(Resource.Id.Ohm2VoltButton);
Button ohm2home = FindViewById<Button>(Resource.Id.Ohm2HomeButton);
ohm2amp.Click += delegate
{
SetContentView(Resource.Layout.AmpScreen);
};
ohm2volt.Click += delegate
{
SetContentView(Resource.Layout.VoltScreen);
};
ohm2home.Click += delegate
{
SetContentView(Resource.Layout.Main);
};
};
I think your problem is that you are replacing the entire view each time - so the button instances are changing.
What happens inside SetContentView is that the InflatorService gets asked to create a brand new set of UI objects based on the passed in XML, the existing UI is wiped clean and then those new UI objects are put in their place.
It doesn't matter if the new UI objects happen to have the same resource identifiers as the old objects - they are still separate instances.
If you want to continue using your current approach, then you need to rewire all your events after each SetContentView - e.g.
ohm2amp.Click += delegate
{
SetContentView(Resource.Layout.AmpScreen);
RewireEvents();
};
with
private void RewireEvents()
{
var ohm2home = FindViewById<Button>(Resource.Id.ohm2home);
ohm2home.Click += { /* todo */ };
// etc
}
alternatively, maybe consider a different UI:
e.g. you could change the Visibility on different child layouts rather than calling SetContentView to replace everything
e.g. or you could use multiple activities (or tabs) instead of a single activity
Hope that helps