I basically have code that starts the keyboard, but it opens in alphanumeric portion and the box for editing is a NumericUpDown with numbers. So, I want to open tabtip.exe aka the onscreen keyboard in windows 8.1 with the numerpad focused. Here is my current code for opening tabtip, but again it does not open with numpad by default:
using System.Runtime.InteropServices; //added for keyboard closure
using System.Windows.Interop; //Keyboard closure - must add reference for WindowsBase
//Added for keyboard closure
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
public static extern bool PostMessage(int hWnd, uint Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(String sClassName, String sAppName);
//open keyboard
void openKeyboard()
{
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe");
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(startInfo);
}
//close keyboard
void closeKeyboard()
{
uint WM_SYSCOMMAND = 274;
uint SC_CLOSE = 61536;
IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
PostMessage(KeyboardWnd.ToInt32(), WM_SYSCOMMAND, (int)SC_CLOSE, 0);
}
There's also seems to be some registry edit you can do, but I can't seem to get it to make the numpad portion of the taptip keyboard in windows 8.1 to show:
Windows 8 Desktop App: Open tabtip.exe to secondary keyboard (for numeric textbox)
Currently with Windows 8.1, not much functionality seems to be programmatically exposed.
The code below will cause the tabtip.exe to read the registry because the original process is killed.
It is not completely reliable, but is a way to for it to respond to some registry values.
The part about docking is optional, it forces it to dock each time via the registry change.
The process.Kill(); should be in a try/catch since it occasionally doesn't have permission and can throw an exception.
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string sClassName, string sAppName);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(int hWnd, uint msg, int wParam, int lParam);
private static void KillTabTip()
{
// Kill the previous process so the registry change will take effect.
var processlist = Process.GetProcesses();
foreach (var process in processlist.Where(process => process.ProcessName == "TabTip"))
{
process.Kill();
break;
}
}
public void ShowTouchKeyboard(bool isVisible, bool numericKeyboard)
{
if (isVisible)
{
const string keyName = "HKEY_CURRENT_USER\\Software\\Microsoft\\TabletTip\\1.7";
var regValue = (int) Registry.GetValue(keyName, "KeyboardLayoutPreference", 0);
var regShowNumericKeyboard = regValue == 1;
// Note: Remove this if do not want to control docked state.
var dockedRegValue = (int) Registry.GetValue(keyName, "EdgeTargetDockedState", 1);
var restoreDockedState = dockedRegValue == 0;
if (numericKeyboard && regShowNumericKeyboard == false)
{
// Set the registry so it will show the number pad via the thumb keyboard.
Registry.SetValue(keyName, "KeyboardLayoutPreference", 1, RegistryValueKind.DWord);
// Kill the previous process so the registry change will take effect.
KillTabTip();
}
else if (numericKeyboard == false && regShowNumericKeyboard)
{
// Set the registry so it will NOT show the number pad via the thumb keyboard.
Registry.SetValue(keyName, "KeyboardLayoutPreference", 0, RegistryValueKind.DWord);
// Kill the previous process so the registry change will take effect.
KillTabTip();
}
// Note: Remove this if do not want to control docked state.
if (restoreDockedState)
{
// Set the registry so it will show as docked at the bottom rather than floating.
Registry.SetValue(keyName, "EdgeTargetDockedState", 1, RegistryValueKind.DWord);
// Kill the previous process so the registry change will take effect.
KillTabTip();
}
Process.Start("c:\\Program Files\\Common Files\\Microsoft Shared\\ink\\TabTip.exe");
}
else
{
var win8Version = new Version(6, 2, 9200, 0);
if (Environment.OSVersion.Version >= win8Version)
{
const uint wmSyscommand = 274;
const uint scClose = 61536;
var keyboardWnd = FindWindow("IPTip_Main_Window", null);
PostMessage(keyboardWnd.ToInt32(), wmSyscommand, (int)scClose, 0);
}
}
}
You can call the above method from a custom version of a TextBox where OnTouchDown is overridden and an additional DependencyProperty is created to indicate if the field uses the NumericKeyboard:
#region NumericKeyboard
public static readonly DependencyProperty NumericKeyboardProperty = DependencyProperty.Register("NumericKeyboard", typeof(bool), typeof(CustomTextBox), new FrameworkPropertyMetadata(false));
/// <summary> Returns/set the "NumericKeyboard" state of the CustomTextBox. </summary>
public bool NumericKeyboard
{
get { return (bool)GetValue(NumericKeyboardProperty); }
set { SetValue(NumericKeyboardProperty, value); }
}
#endregion
protected override void OnTouchDown(TouchEventArgs e)
{
base.OnTouchDown(e);
Focus();
if (IsReadOnly == false)
ShowTouchKeyboard(true, NumericKeyboard);
}
Currently, I have not had any success using similar techniques to position the TabTip window around the screen when in a floating (non-docked) state.
Related
I am working on a console executable that may run in multi monitor environment.
It may be started by double clicking on the Exe file name inside Windows Explorer.
I want to move the console to the same monitor as the Windows Explorer window that started it. Is there any way to do it?
I was able to get parent process and get MainWindowHandle.
But it will not give me the correct window. It will give me the first Explorer window. See code below. SetupConsoleWindow is the main function.
internal static class NativeMethods
{
internal const int SWP_NOSIZE = 0x0001;
[DllImport("kernel32.dll")]
internal static extern bool AllocConsole();
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
internal static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetConsoleWindow();
}
public static Process GetParentProcess()
{
var currentProcessName = Process.GetProcessById(Process.GetCurrentProcess().Id).ProcessName;
var processesByName = Process.GetProcessesByName(currentProcessName);
for (var index = 0; index < processesByName.Length; index++)
{
string processIndexdName = index == 0 ? currentProcessName : currentProcessName + "#" + index;
var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
if ((int)processId.NextValue() == Process.GetCurrentProcess().Id)
break;
}
var parentPerformanceCounter = new PerformanceCounter("Process", "Creating Process ID", currentProcessName);
Process parentProcess = Process.GetProcessById((int)parentPerformanceCounter.NextValue());
return parentProcess;
}
public static void SetupConsoleWindow()
{
NativeMethods.AllocConsole();
var parentProcess = GetParentProcess();
if (parentProcess != null)
{
IntPtr consoleWindowHandle = NativeMethods.GetConsoleWindow();
Screen parentScreen = Screen.FromHandle(parentProcess.MainWindowHandle);
Rectangle monitor = parentScreen.WorkingArea;
NativeMethods.SetWindowPos(consoleWindowHandle, 0, monitor.Left, monitor.Top, 0, 0, NativeMethods.SWP_NOSIZE);
}
}
So what you want to do is launch your program on the same monitor as the Windows Explorer window that started it. Doing this the way you currently intend to may be technically possible, but it would be cumbersome and flaky. It would involve enumerating all the open windows, figuring out which ones are Explorer windows, then for each of those which folder is being viewed and then which file is currently selected. You would then compare the name of that file with your program's name and, if multiple such windows are found, choose the most top-level one. You would have to hope that the file did not somehow get deselected between the double click and your main().
This process is well documented here. For reference, here is what the code to get the currently selected item looks like in C++:
#include <shlobj.h>
#include <exdisp.h>
TCHAR g_szPath[MAX_PATH];
TCHAR g_szItem[MAX_PATH];
void CALLBACK RecalcText(HWND hwnd, UINT, UINT_PTR, DWORD)
{
HWND hwndFind = GetForegroundWindow();
g_szPath[0] = TEXT('\0');
g_szItem[0] = TEXT('\0');
IShellWindows *psw;
if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL,
IID_IShellWindows, (void**)&psw))) {
VARIANT v;
V_VT(&v) = VT_I4;
IDispatch *pdisp;
BOOL fFound = FALSE;
for (V_I4(&v) = 0; !fFound && psw->Item(v, &pdisp) == S_OK;
V_I4(&v)++) {
IWebBrowserApp *pwba;
if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) {
HWND hwndWBA;
if (SUCCEEDED(pwba->get_HWND((LONG_PTR*)&hwndWBA)) &&
hwndWBA == hwndFind) {
fFound = TRUE;
IServiceProvider *psp;
if (SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) {
IShellBrowser *psb;
if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser,
IID_IShellBrowser, (void**)&psb))) {
IShellView *psv;
if (SUCCEEDED(psb->QueryActiveShellView(&psv))) {
IFolderView *pfv;
if (SUCCEEDED(psv->QueryInterface(IID_IFolderView,
(void**)&pfv))) {
IPersistFolder2 *ppf2;
if (SUCCEEDED(pfv->GetFolder(IID_IPersistFolder2,
(void**)&ppf2))) {
LPITEMIDLIST pidlFolder;
if (SUCCEEDED(ppf2->GetCurFolder(&pidlFolder))) {
if (!SHGetPathFromIDList(pidlFolder, g_szPath)) {
lstrcpyn(g_szPath, TEXT("<not a directory>"), MAX_PATH);
}
int iFocus;
if (SUCCEEDED(pfv->GetFocusedItem(&iFocus))) {
LPITEMIDLIST pidlItem;
if (SUCCEEDED(pfv->Item(iFocus, &pidlItem))) {
IShellFolder *psf;
if (SUCCEEDED(ppf2->QueryInterface(IID_IShellFolder,
(void**)&psf))) {
STRRET str;
if (SUCCEEDED(psf->GetDisplayNameOf(pidlItem,
SHGDN_INFOLDER,
&str))) {
StrRetToBuf(&str, pidlItem, g_szItem, MAX_PATH);
}
psf->Release();
}
CoTaskMemFree(pidlItem);
}
}
CoTaskMemFree(pidlFolder);
}
ppf2->Release();
}
pfv->Release();
}
psv->Release();
}
psb->Release();
}
psp->Release();
}
}
pwba->Release();
}
pdisp->Release();
}
psw->Release();
}
InvalidateRect(hwnd, NULL, TRUE);
}
However, you may be making this more complicated than it needs to be. Consider this instead:
Get the current mouse coordinates with Cursor.Position (or GetCursorPos)
Get the monitor on which the mouse cursor is present
Move your window to that monitor
I'm trying to embed the osk in a wpf window or a user control and I've found the code below and it's working for notepad but for tabtip.exe, it's saying that it doesn't have a graphical interface??
WaitForInputIdle failed. This could be because the process does not have a graphical interface.
I tried letting it sleep for awhile instead of calling waitForInputIdle method but it throws another exception:
Process has exited, so the requested information is not available.
But in my task manager, I can still see TabTip.exe running.
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private System.Windows.Forms.Panel _panel;
private Process _process;
public MainWindow()
{
InitializeComponent();
_panel = new System.Windows.Forms.Panel();
windowsFormsHost1.Child = _panel;
}
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOACTIVATE = 0x0010;
private const int GWL_STYLE = -16;
private const int WS_CAPTION = 0x00C00000;
private const int WS_THICKFRAME = 0x00040000;
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (_process != null)
{
_process.Refresh();
_process.Close();
}
}
private void ResizeEmbeddedApp()
{
if (_process == null)
return;
SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)_panel.ClientSize.Width, (int)_panel.ClientSize.Height, SWP_NOZORDER | SWP_NOACTIVATE);
}
protected override Size MeasureOverride(Size availableSize)
{
Size size = base.MeasureOverride(availableSize);
ResizeEmbeddedApp();
return size;
}
private void button1_Click_1(object sender, RoutedEventArgs e)
{
button1.Visibility = Visibility.Hidden;
ProcessStartInfo psi = new ProcessStartInfo("C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe");
_process = Process.Start(psi);
Thread.Sleep(500);
//_process.WaitForInputIdle();
SetParent(_process.MainWindowHandle, _panel.Handle);
// remove control box
int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
style = style & ~WS_CAPTION & ~WS_THICKFRAME;
SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);
// resize embedded application & refresh
ResizeEmbeddedApp();
}
}
}
Edit: Inspired by rene's comment, I've tried to obtain the window ptr as below and used spy++ to verify that the address that FindWindow gives is pointing to the correct window, but it's still not moving:
IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
int style = GetWindowLong(KeyboardWnd, GWL_STYLE);
style = style & ~WS_CAPTION & ~WS_THICKFRAME;
SetWindowLong(KeyboardWnd, GWL_STYLE, style);
SetWindowPos(KeyboardWnd, IntPtr.Zero, 0, 0, (int)_panel.ClientSize.Width, (int)_panel.ClientSize.Height, SWP_NOZORDER | SWP_NOACTIVATE);
Edit 2: My first thought was that tab tip couldn't be resized, but then I noticed a behavior when I try to move the window across two different screen, it'll resize to fit the screen size, so I'm sure there must be a way to resize, so I started spy++(x64) to check :
Edit 3: after tinkering abit with user32 api and no progress, I've tried to use a memory scanner to scan for the x and y position of tabtip and change it, however, it's not refreshing until a repaint is triggered, I'm wondering the feasibility going down that path.
Can you try to run your handle code in STA thread? I had a similar issue with native window, which I had resolved using STA thread.
var thread = new Thread(() => {
// Your code here
});
thread.TrySetApartmentState(ApartmentState.STA);
thread.Start();
I had a similar problem, and the reason I had it was that I started a program that needed to be run by an administrator with a non-administrative program, and it would pop up with WaitForInputIdle failed. This could be because the process does not have a graphical interface, so I assume you try starting your program with an administrator
i want to disable the scrolling feature of richtextbox in c#. i just want to make richtextbox to allow user to enter only in its size area, means no vertical scrolling for user. just like MS-word or open Office Pages.thanx in advance.
You should override WndProc and block WM_SETFOCUS.
protected override void WndProc(ref Message m)
{
if(m.Msg != WM_SETFOCUS)
base.WndProc(ref m);
}
Here is a tutorial about this : How to: C# - Prevent RichTextBox from auto scrolling
This worked for me.
First thing as you may have seen in other posts you need access to user32.dll from C#.
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hwndLock,Int32 wMsg,Int32 wParam, ref Point pt);
We need to make some constant declaration to make the SendMessage calls properly.
private const int WM_USER = 0x400;
private const int EM_HIDESELECTION = WM_USER + 63;
private const int WM_SETREDRAW = 0x000B;
private const int EM_GETSCROLLPOS = WM_USER + 221;
private const int EM_SETSCROLLPOS = WM_USER + 222;
Then, some public static methods to be used whenever we need to stop scrolling.
public static void Suspend(Control control)
{
Message msgSuspendUpdate = Message.Create(control.Handle, WM_SETREDRAW, IntPtr.Zero,
IntPtr.Zero);
NativeWindow window = NativeWindow.FromHandle(control.Handle);
window.DefWndProc(ref msgSuspendUpdate);
}
public static void Resume(Control control)
{
// Create a C "true" boolean as an IntPtr
IntPtr wparam = new IntPtr(1);
Message msgResumeUpdate = Message.Create(control.Handle, WM_SETREDRAW, wparam,
IntPtr.Zero);
NativeWindow window = NativeWindow.FromHandle(control.Handle);
window.DefWndProc(ref msgResumeUpdate);
control.Invalidate();
}
public static Point GetScrollPoint(Control control) {
Point point = new Point();
SendMessage(control.Handle, EM_GETSCROLLPOS, 0, ref point);
return point;
}
public static void SetScrollPoint(Control control, Point point)
{
SendMessage(control.Handle, EM_SETSCROLLPOS, 0, ref point);
}
The Suspend method stops the Control to make a redraw on the screen. The Resume method restarts redraws on the screen for the given Control.
The GetScrollPoint method gets the actual Point where the scroll caret is located. The SetScrollPoint puts the scroll caret at the given point.
How to use these methods? First, given a Control you need to stop autoscroll, make the call to Suspend, then to GetScrollPoint, (make what you need to do with the control, like highlight or append text) then SetScrollPoint and finally Resume.
In my case, I wanted to copy the entire line of a RichTextBox at any time when the cursor moves from line to line. (Doing so produce a scroll on long lines).
This is my working method:
private int intLastLine = -1;
private void richTextBoxSwitch_SelectionChanged(object sender, EventArgs e)
{
try
{
if (this.richTextBoxSwitch.TextLength > 0)
{
ControlBehavior.Suspend(this.richTextBoxSwitch);
Point point = ControlBehavior.GetScrollPoint(this.richTextBoxSwitch);
int intSelectionStartBackup = this.richTextBoxSwitch.SelectionStart;
int intSelectionLengthBackup = this.richTextBoxSwitch.SelectionLength;
int intCharIndex = this.richTextBoxSwitch.GetFirstCharIndexOfCurrentLine();
int intLine = this.richTextBoxSwitch.GetLineFromCharIndex(intCharIndex);
this.richTextBoxSwitch.SuspendLayout();
if (intLastLine != intLine)
{
intLastLine = intLine;
int intLength = this.richTextBoxSwitch.Lines[intLine].Length;
this.richTextBoxSwitch.Select(intCharIndex, intLength);
this.richTextBoxSwitch.BackColor = ColorMessageBackground;
strData = this.richTextBoxSwitch.SelectedText;
this.textBoxMessageSelected.Text = strData.Trim();
this.richTextBoxSwitch.Select(intSelectionStartBackup, intSelectionLengthBackup);
}
this.richTextBoxSwitch.ResumeLayout();
ControlBehavior.SetScrollPoint(this.richTextBoxSwitch, point);
ControlBehavior.Resume(this.richTextBoxSwitch);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Hope this helps!
I've tried several solutions found, like the one ->
http://www.pcreview.co.uk/forums/console-writeline-hangs-if-user-click-into-console-window-t1412701.html
But, I observed that mode in GetConsoleMode(IntPtr hConsoleHandle, out int mode) will be different for different console app. It is not constant.
Can I disable mouse clicks (right/left buttons) on a console application to achieve the same scenario. I found that it can be done with IMessageFilter but only for Window Form Application and not for console application.
For those like me that like no-brainer code to copy/paste, here is the code inspired from the accepted answer:
using System;
using System.Runtime.InteropServices;
static class DisableConsoleQuickEdit {
const uint ENABLE_QUICK_EDIT = 0x0040;
// STD_INPUT_HANDLE (DWORD): -10 is the standard input device.
const int STD_INPUT_HANDLE = -10;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll")]
static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
internal static bool Go() {
IntPtr consoleHandle = GetStdHandle(STD_INPUT_HANDLE);
// get current console mode
uint consoleMode;
if (!GetConsoleMode(consoleHandle, out consoleMode)) {
// ERROR: Unable to get console mode.
return false;
}
// Clear the quick edit bit in the mode flags
consoleMode &= ~ENABLE_QUICK_EDIT;
// set the new mode
if (!SetConsoleMode(consoleHandle, consoleMode)) {
// ERROR: Unable to set console mode
return false;
}
return true;
}
}
If you want to disable quick edit mode, you need to call GetConsoleMode to get the current mode. Then clear the bit that enables quick edit, and call SetConsoleMode. Assuming you have the managed prototypes for the unmanaged functions, you would write:
const int ENABLE_QUICK_EDIT = 0x0040;
IntPtr consoleHandle = GetConsoleWindow();
UInt32 consoleMode;
// get current console mode
if (!GetConsoleMode(consoleHandle, out consoleMode))
{
// Error: Unable to get console mode.
return;
}
// Clear the quick edit bit in the mode flags
mode &= ~ENABLE_QUICK_EDIT;
// set the new mode
if (!SetConsoleMode(consoleHandle, consoleMode))
{
// ERROR: Unable to set console mode
}
If you want to disable mouse input, you want to clear the mouse input bit.
const int ENABLE_MOUSE_INPUT = 0x0010;
mode &= ~ENABLE_MOUSE_INPUT;
Having read above answers, GetConsoleWindow() can not be used. Instead GetStdHandle() must be used.
So here's a copy and paste class for enabling/disabling QuickEditMode. Call ConsoleWindow.QuickEditMode(false); to disable quick edit mode for the console window.
using System;
using System.Runtime.InteropServices;
public static class ConsoleWindow
{
private static class NativeFunctions
{
public enum StdHandle : int
{
STD_INPUT_HANDLE = -10,
STD_OUTPUT_HANDLE = -11,
STD_ERROR_HANDLE = -12,
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle); //returns Handle
public enum ConsoleMode : uint
{
ENABLE_ECHO_INPUT = 0x0004,
ENABLE_EXTENDED_FLAGS = 0x0080,
ENABLE_INSERT_MODE = 0x0020,
ENABLE_LINE_INPUT = 0x0002,
ENABLE_MOUSE_INPUT = 0x0010,
ENABLE_PROCESSED_INPUT = 0x0001,
ENABLE_QUICK_EDIT_MODE = 0x0040,
ENABLE_WINDOW_INPUT = 0x0008,
ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200,
//screen buffer handle
ENABLE_PROCESSED_OUTPUT = 0x0001,
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002,
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004,
DISABLE_NEWLINE_AUTO_RETURN = 0x0008,
ENABLE_LVB_GRID_WORLDWIDE = 0x0010
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
}
public static void QuickEditMode(bool Enable)
{
//QuickEdit lets the user select text in the console window with the mouse, to copy to the windows clipboard.
//But selecting text stops the console process (e.g. unzipping). This may not be always wanted.
IntPtr consoleHandle = NativeFunctions.GetStdHandle((int)NativeFunctions.StdHandle.STD_INPUT_HANDLE);
UInt32 consoleMode;
NativeFunctions.GetConsoleMode(consoleHandle, out consoleMode);
if (Enable)
consoleMode |= ((uint)NativeFunctions.ConsoleMode.ENABLE_QUICK_EDIT_MODE);
else
consoleMode &= ~((uint)NativeFunctions.ConsoleMode.ENABLE_QUICK_EDIT_MODE);
consoleMode |= ((uint)NativeFunctions.ConsoleMode.ENABLE_EXTENDED_FLAGS);
NativeFunctions.SetConsoleMode(consoleHandle, consoleMode);
}
}
For those who use vb.net
Const ENABLE_QUICK_EDIT As UInteger = &H40
Const STD_INPUT_HANDLE As Integer = -10
<DllImport("kernel32.dll", SetLastError:=True)>
Public Function GetStdHandle(ByVal nStdHandle As Integer) As IntPtr
End Function
<DllImport("kernel32.dll")>
Private Function GetConsoleMode(ByVal hConsoleHandle As IntPtr, <Out> ByRef lpMode As UInteger) As Boolean
End Function
<DllImport("kernel32.dll")>
Private Function SetConsoleMode(ByVal hConsoleHandle As IntPtr, ByVal dwMode As UInteger) As Boolean
End Function
Friend Function Go() As Boolean
Dim consoleHandle As IntPtr = GetStdHandle(STD_INPUT_HANDLE)
Dim consoleMode As UInteger
If Not GetConsoleMode(consoleHandle, consoleMode) Then
Return False
End If
consoleMode = consoleMode And Not ENABLE_QUICK_EDIT
If Not SetConsoleMode(consoleHandle, consoleMode) Then
Return False
End If
Return True
End Function
sub main()
go()
end sub
By used combination of codes on below, I'm be able to enable or disable the Quick Edit mode.
const int ENABLE_QUICK_EDIT = 0x0040;
// STD_INPUT_HANDLE (DWORD): -10 is the standard input device.
const int STD_INPUT_HANDLE = -10;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
static extern bool GetConsoleMode(IntPtr hConsoleHandle, out int lpMode);
[DllImport("kernel32.dll")]
static extern bool SetConsoleMode(IntPtr hConsoleHandle, int dwMode);
To enable, simple do currentConsoleMode &= ENABLE_QUICK_EDIT;
And to disable, do
currentConsoleMode &= ~ENABLE_QUICK_EDIT
And then call SetConsoleMode.
I just happened to stumble over the same problem with quick edit mode enabled in my console application, which is written in C, and has been working under windows 7 32 bit for ages. After porting (well not really porting, but adapting some code lines) it to windows 10 64 Bit (still being a 32 bit application), I observed the same behaviour.
So I searched for a solution.
But for a reason unknown to me, the code works the other way round, i.e setting the bit ENABLE_QUICK_EDIT_MODE in the mode parameter actually disables quick edit mode. And resetting the bit enables the quick edit mode...???
Here is my code:
/// <summary>
/// This flag enables the user to use the mouse to select and edit text. To enable
/// this option, you must also set the ExtendedFlags flag.
/// </summary>
const int QuickEditMode = 64;
// ExtendedFlags must be combined with
// InsertMode and QuickEditMode when setting
/// <summary>
/// ExtendedFlags must be enabled in order to enable InsertMode or QuickEditMode.
/// </summary>
const int ExtendedFlags = 128;
BOOLEAN EnableQuickEdit()
{
HWND conHandle = GetStdHandle(STD_INPUT_HANDLE);
int mode;
DWORD dwLastError = GetLastError();
if (!GetConsoleMode(conHandle, &mode))
{
// error getting the console mode. Exit.
dwLastError = GetLastError();
return (dwLastError == 0);
}
else
dwLastError = 0;
mode = mode & ~QuickEditMode;
if (!SetConsoleMode(conHandle, mode | ExtendedFlags))
{
// error setting console mode.
dwLastError = GetLastError();
}
else
dwLastError = 0;
return (dwLastError == 0);
}
BOOLEAN DisableQuickEdit()
{
HWND conHandle = GetStdHandle(STD_INPUT_HANDLE);
int mode;
DWORD dwLastError = GetLastError();
if (!GetConsoleMode(conHandle, &mode))
{
// error getting the console mode. Exit.
dwLastError = GetLastError();
return (dwLastError == 0);
}
else
dwLastError = 0;
mode = mode | QuickEditMode;
if (!SetConsoleMode(conHandle, mode))
{
// error getting the console mode. Exit.
dwLastError = GetLastError();
}
else
dwLastError = 0;
return (dwLastError == 0);
}
Greetings Wolfgang
How does one run screensaver within Windows Form as background for it?
User also can interact with form controls while screensaver running.
[Why this?]
We have a case which we need to run Windows Bubbles screensaver while user
can continue interacting with form controls?
You can use the following code :
private void ShowScreenSaver(Control displayControl)
{
using (RegistryKey desktopKey = Registry.CurrentUser.OpenSubKey(#"Control Panel\Desktop"))
{
if (desktopKey != null)
{
string screenSaverExe = desktopKey.GetValue("SCRNSAVE.EXE") as string;
if (!string.IsNullOrEmpty(screenSaverExe))
{
Process p = Process.Start(screenSaverExe, "/P " + displayControl.Handle);
p.WaitForInputIdle();
IntPtr hwnd = p.MainWindowHandle;
if (hwnd != IntPtr.Zero)
{
SetParent(hwnd, displayControl.Handle);
Rectangle r = displayControl.ClientRectangle;
MoveWindow(hwnd, r.Left, r.Top, r.Width, r.Height, true);
}
}
}
}
}
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hwndChild, IntPtr hwndParent);
[DllImport("user32.dll")]
static extern bool MoveWindow(IntPtr hwnd, int x, int y, int width, int height, bool repaint);
The parameter is the form or control in which you want to display the screensaver preview. Note that the screensaver will briefly appear in full screen before it is resized.