I am creating a GUI in using VC++ CLR windows form and wanted to make a hotkey to restore my windows from the system tray that I have minimized. I've found that RegisterHotKey is a way to make a global hotkey in the system but I don't understand how to make use of it inside my code.
Any thoughts??
First you need to #include the Windows headers, put it in the stdafx.h precompiled header file for example:
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
#pragma once
#include <Windows.h>
#pragma comment(lib, "user32.lib")
The #pragma ensures that the linker will link the import library for user32.dll, required to link RegisterHotKey().
Next, inside the Form class you need to override the OnHandleCreated() method. It will run whenever the native window for the Form is created, something that can happen more than once. Make that look like this:
protected:
virtual void OnHandleCreated(EventArgs^ e) override {
__super::OnHandleCreated(e);
RegisterHotKey((HWND)this->Handle.ToPointer(), 1,
MOD_ALT | MOD_CONTROL, (UINT)Keys::F1);
}
I hard-coded the hotkey to Ctrl+Alt+F1, change that to the one you want to use. You can add additional hotkeys, change the id argument (2nd argument, I used 1).
Then you need to detect the WM_HOTKEY message that windows will send to you when the user presses the key. That requires overriding the form's WndProc() method, like this:
protected:
virtual void WndProc(Message% m) override {
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == 1) {
this->WindowState = FormWindowState::Normal;
this->BringToFront();
}
__super::WndProc(m);
}
Test this by minimizing the form, pressing Ctrl+Alt+F1 and you'll see the window getting restored and moved back into the foreground.
Thanks for your help Hans, I tried with the codes but it didn't really work like I wanted it to. My program will be minimized into the system tray with the codes below
private:
System::Void MyForm::MyForm_Resize(System::Object^ sender, System::EventArgs^ e) {
if (WindowState == FormWindowState::Minimized)
{
Hide();
}
}
If I commented out the part where it hides as it minimize, it worked out fine though.
Related
In my working environment I can have up to 10 command prompt windows open, each one set up to work in a different context. Having all of them open, I find myself having to switch between several of them to find the right one that I want to work with.
I am already setting different foreground and background colors of each window based on some criteria, but it would be much more easier to distinguish between them by having a different colored icon in the taskbar. That way, I would not even have to maximize/bring them to focus to find the right one from the get-go.
Is there a way that I can change the taskbar icon of the currently running command prompt window programmatically by executing batch commands in it?
There is no "built-in" way to do that, like there is the color command from cmd.exe to change the colors.
You could either search the internet for some utilitiy, or roll your own, for example in C#, by invoking the SetConsoleIcon Win32 API. Note however, that this API is not officially documented, YMMV.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint SetConsoleIcon(IntPtr iconHandle);
static void Main(string[] args)
{
if (args[0].Equals("--reset", StringComparison.OrdinalIgnoreCase))
{
SetConsoleIcon(IntPtr.Zero);
}
else
{
// Use this to load an icon from an icon file instead:
// var icon = new Icon(args[0]); // load from .ico file
// Extract icon from given executable/dll.
using (var icon = Icon.ExtractAssociatedIcon(args[0]))
{
if (icon != null)
SetConsoleIcon(icon.Handle);
}
}
}
}
You should be able to compile this using csc.exe setconico.cs (assuming you named the file setconico.cs). This will generate setconico.exe, which you can use like this:
Set the current console icon of the console you run this in, to the icon of notepad.exe
c:\> setconico.exe c:\windows\notepad.exe
You might also be able to write the above code in PowerShell, if you don't want to compile a separate utility.
I made a Windows Form Application and it works great.
But now I got a requirement that needs that the application reads parameters to be able to run as a Scheduled Task.
I made my research and with the instructions
Environment.GetCommandLineArgs();
I can read and do stuff with the parameters, that will replace the user interaction like the combo selection that the application requires,etc.
My big questions is Where do you place the code?
A) Code After the InitializeComponent() in the form. (I dont understand if the code in the form_load will enter if I use it as a hidden Scheduled Task)
B) In the Program.cs after the Application.Run(new Form1());
C) Any other place
be able to run as a Scheduled Task
With no user interaction (and thus no need for a user interface), a Console Application would be ideal for this. And the main entry point for a Console Application is Program.cs. Therein, command-line arguments are even by default passed to the entry point:
static void Main(string[] args)
{
// "args" contains command line arguments
}
So I suspect the ideal setup here would be to have two separately deployed application instances (one as a Windows Form Applications and one as a Console Application), which share business logic in a Class Library, and separately handle the two different usage scenarios you describe.
Think of it like this... Why try to force the same tool to do two very different jobs when you can just use the right tool for each job? (Golden hammers are traditionally bad things.)
If you really want to use the Windows Forms Application as the scheduled task, then it too has the same Program.cs entry point. By default it's usually something like this:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
But the behavior of the entry point is the same. You can simply add the method arguments and perform logic based on that command-line input. Perhaps something like this:
[STAThread]
static void Main(string[] args)
{
if (CheckForSomeArg(args))
{
// perform the automated tasks, pretend to be a Console Application
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
So if the command-line arguments you're looking for are given, the "scheduled task" is performed. Otherwise, the user interface is displayed.
My WPF application is using MahApps.Metro, it require the MahApps.Metro.dll and the system.windows.interactivity.dll. How do I shift them to a folder, for example folder bin and still make them work? If I just shift them, the application would not start at all. Please help!
It would probably be best if you left all these DLL files alone and let the .NET Framework sort it all out. If you have to move them anyway, you may edit the properties of a reference and set the Copy Local property to false, so it won't output the DLL file when compiling.
In you App.cs file (assuming you're using C#) add the following:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if (args.Name.StartsWith("MahApps.Metro"))
{
System.IO.BinaryReader stream = new BinaryReader(new FileStream("bin/MahApps.Metro.dll", FileMode.Open));
byte[] assembly = stream.ReadBytes((int)stream.BaseStream.Length);
return Assembly.Load(assembly);
}
return null;
}
Edit the above code to suit your needs so that it will work exactly the way you want it to.
You will have to verify that all the DLL files you're using are the same version as the one being targeted, or .NET will throw an exception. Also, the DLL file may not exist and loading the stream might raise some problems if it is used on a network location. All in all it is likely to work, but it's probably not worth the trouble.
I need to check if a c# WinForm Window (FORM Class) has been initialized and waiting for user events. But I could not find out how to manage that.
Therefore I had the idea to set the Control.IsAccessible Flag of the Form to true, within the OnLoad Event of the Windows Form.
My question is now, what is the Control.IsAccessible Flag origin intended for? Or is there an other solution to check if the Winform is initialized.
Thanks for your help
I do not know what IsAccessible is intended for but for the check you are doing you want Created
if(myForm.Created)
{
//Do stuff
}
I had a whole bunch of problems with it, here is one of my old question on SO that helped me out a lot with it.
Control.IsAccessible just means the control is visible to accessibility applications.
You can check myForm.Created to see if the window exists.
You can also register an event handler for the Application.Idle event, which occurs when the application has finished initializing and is ready to begin processing windows messages.
Here is a common usage:
public int Main(string[] args)
{
Application.Idle += WaitUntilInitialized;
}
private void WaitUntilInitialized(object source, EventArgs e)
{
// Avoid processing this method twice
Application.Idle -= WaitUntilInitialized;
// At this point, the UI is visible and waiting for user input.
// Begin work here.
}
I have a C++/CLI GUI application and I want to display an image as a visual aid for the user to see what step in a procedure they're at. This image will need to be changed each time the user selects the new step.
Currently I'm using a picture box and have an image loaded from the disk at run time. So there are a few things I need to know here:
Is a picture box the best thing to use for this purpose or is there another control that would better suit?
How do embed the images in the executable and load them from there instead of a file that exists on disk.
How do I load a new image (I'm guessing that this will be fairly obvois if I can crack point 2)?
I've seen a few answers which relate to C# but I've not seen anything which looks like it translates to doing things in a C++/CLI app. Any suggestions would be very welcome.
Well it may not be the best solution, but the following works.
Create a new Windows Forms Application
Add these libraries to your linker settings (Project Proerties -> Link -> Input -> Additional Dependencies):
User32.lib Gdi32.lib
Add these headers:
#include <windows.h>
#include "resource.h"
Add these namespaces:
using namespace System::Reflection;
using namespace System::Runtime::InteropServices;
Add a pair of bitmaps to your resources and call them IDB_BITMAP1 and IDB_BITMAP2.
Add a picture box called m_pictureBox1.
Add a button and double-click the button to add an on-click handler:
System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
// Remove any previously stored images
if(m_pictureBox1->Image != nullptr)
{
delete m_pictureBox1->Image;
}
// Pick a new bitmap
static int resource = IDB_BITMAP1;
if( resource == IDB_BITMAP2)
{
resource = IDB_BITMAP1;
}
else
{
resource = IDB_BITMAP2;
}
// Get the primary module
Module^ mod = Assembly::GetExecutingAssembly()->GetModules()[0];
// Get the instance handle
IntPtr hinst = Marshal::GetHINSTANCE(mod);
// Get the bitmap as unmanaged
HANDLE hbi = LoadImage((HINSTANCE) hinst.ToPointer(),MAKEINTRESOURCE(resource),IMAGE_BITMAP,0,0,LR_DEFAULTCOLOR);
// import the unmanaged bitmap into the managed side
Bitmap^ bi = Bitmap::FromHbitmap(IntPtr(hbi));
// insert the bitmap into the picture box
m_pictureBox1->Image = bi;
// Free up the unmanaged bitmap
DeleteObject(hbi);
// Free up the instance and module
delete hinst;
delete mod;
}
..et voila the bitmaps are stored neatly in you app and each time you click the button the images will swap.