I am working on a .net windows forms control where i have used the below code to use modify the caret in my custom textbox
[DllImport("User32.dll")]
static extern bool CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight);
[DllImport("User32.dll")]
static extern bool SetCaretPos(int x, int y);
[DllImport("User32.dll")]
static extern bool DestroyCaret();
[DllImport("User32.dll")]
static extern bool ShowCaret(IntPtr hWnd);
[DllImport("User32.dll")]
static extern bool HideCaret(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool SetCaretBlinkTime(uint uMSeconds);
protected override void OnGotFocus(System.EventArgs e)
{
CreateCaret(this.Handle, IntPtr.Zero, 8, 14);
SetCaretPos(2, 1);
ShowCaret(this.Handle);
SetCaretBlinkTime(100);
base.OnGotFocus(e);
}
protected override void OnLostFocus(EventArgs e)
{
DestroyCaret();
base.OnLostFocus(e);
}
but i found out that once i run the project , the blinking rate of my windows cursor have changed too till i restart my windows xp (sp2) .
any suggestion on why it is happening ?
To draw a caret by your self:
public class CueTextBox : TextBox
{
[DllImport("User32.dll")]
static extern bool GetCaretPos(out POINT pt);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public UInt32 x;
public UInt32 y;
};
[DllImport("User32.dll")]
static extern bool DestroyCaret();
[DllImport("User32.dll")]
static extern bool HideCaret(IntPtr hWnd);
[DllImport("user32.dll")]
static extern uint GetCaretBlinkTime();
[DllImport("User32.dll")]
static extern bool SetTimer(IntPtr hWnd, IntPtr nIDEvent, uint uElapse, IntPtr lpTimerFunc);
[DllImport("User32.dll")]
static extern bool KillTimer(IntPtr hWnd, IntPtr nIDEvent);
[DllImport("User32.dll")]
static extern bool InvalidateRect(IntPtr hWnd, IntPtr lpRect, Int32 bErase);
private bool show = true;
protected override void OnGotFocus(System.EventArgs e)
{
HideCaret(this.Handle);
IntPtr nIDEvent = new IntPtr(1);
SetTimer(this.Handle, nIDEvent, 100, IntPtr.Zero);
base.OnGotFocus(e);
}
protected override void OnLostFocus(EventArgs e)
{
//SetCaretBlinkTime(530);
IntPtr nIDEvent = new IntPtr(1);
KillTimer(this.Handle, nIDEvent);
show = false;
base.OnLostFocus(e);
}
protected virtual void OnTimer(EventArgs e)
{
InvalidateRect(this.Handle, IntPtr.Zero, 0);
show = !show;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
POINT pt = new POINT();
GetCaretPos(out pt);
SolidBrush brush;
if (show)
{
brush = new SolidBrush(Color.Black);
e.Graphics.FillRectangle(brush, pt.x, pt.y, 8, 14);
}
}
const int WM_PAINT = 0x000F;
const int WM_SETFOCUS = 0x0007;
const int WM_KILLFOCUS = 0x0008;
const int WM_TIMER = 0x0113;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT)
{
this.OnPaint(new PaintEventArgs(Graphics.FromHwnd(m.HWnd), this.ClientRectangle));
}
if (m.Msg == WM_SETFOCUS)
{
this.OnGotFocus(new EventArgs());
}
if (m.Msg == WM_KILLFOCUS)
{
this.OnLostFocus(new EventArgs());
}
if (m.Msg == WM_TIMER)
{
this.OnTimer(new EventArgs());
}
}
}
Use SetTimer to set a "blinktime", and then InvalidateRect in the WM_TIMER to trigger WM_PAINT message, then simulate the blinking caret in OnPaint method.
Related
I'm trying to minimize window folders and applications with voice ( speech recognition ) and this is my code :
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern bool SetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
private struct POINTAPI
{
public int x;
public int y;
}
private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
private struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public POINTAPI ptMinPosition;
public POINTAPI ptMaxPosition;
public RECT rcNormalPosition;
}
private void button1_Click(object sender, EventArgs e)
{
WindowAction_MinimizeNotepad();
}
void WindowAction_MinimizeNotepad()
{
System.IntPtr app_hwnd;
WINDOWPLACEMENT wp = new WINDOWPLACEMENT();
app_hwnd = FindWindow("chrome", null);
GetWindowPlacement(app_hwnd, ref wp);
wp.showCmd = 2;
SetWindowPlacement(app_hwnd, ref wp);
}
i know how to use that code with button but i don't know how to use it with speech recognition so, how can i minimize windows with voice ? thanks.
First You need to Register for speech recognition event like:
On Page load
// Register handler for the SpeechRecognized event.
recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(srEvent_SpeechRecognized);
Then create a speech recognition event handler, Like :
void srEvent_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
this.WindowState = FormWindowState.Minimized;
}
You may want to have a look at Microsoft.Speech.Recognition.SpeechRecognitionEngine.
Using this you can subscribe to events and proceed with whatever action you want to perform on those events.
Get more information at https://msdn.microsoft.com/en-us/library/hh378426(v=office.14).aspx
I'm trying to implement a screencast application and i need to show the location of mouse on click.
How can I show the location of the pointer(mouse) like there is default on windows with the CTRL key if you enable that option on (Mouse Properties-> Pointer Options -> Show location of pointer when I press the CTRL key)
Is there any good solution rather than just draw a circle on canvas with a storyboard to getting smaller and then disappear ?
You can get the mouse location using Cursor.Position
Then you can draw your circle around the the cursor location.
So if you need it by a key press like with the ctrl scenario you can bind an event listener for key press or if you need something constant you can set an event listener on the mouse move.
Hope it will help
Liron
After some time i did it with that code.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public static class MouseHook
{
public class MSLLHOOKSTRUCTEventArgs : EventArgs
{
private readonly MSLLHOOKSTRUCT _hookStruct;
public MSLLHOOKSTRUCTEventArgs(MSLLHOOKSTRUCT hookStruct)
{
_hookStruct = hookStruct;
}
public MSLLHOOKSTRUCT HookStruct
{
get { return _hookStruct; }
}
}
public static event EventHandler<MSLLHOOKSTRUCTEventArgs> MouseDown = delegate { };
public static event EventHandler<MSLLHOOKSTRUCTEventArgs> MouseUp = delegate { };
public static event EventHandler<MSLLHOOKSTRUCTEventArgs> MouseMove = delegate { };
public static bool Started { get; set; }
static MouseHook()
{
Started = false;
}
public static void Start()
{
Debug.WriteLine("MouseHook.Start");
_hookID = SetHook(_proc);
Started = true;
}
public static void Stop()
{
Debug.WriteLine("MouseHook.Stop");
UnhookWindowsHookEx(_hookID);
Started = false;
MouseDown = null;
MouseUp = null;
MouseMove = null;
}
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(LowLevelMouseProc proc)
{
IntPtr hook = SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle("user32"), 0);
if (hook == IntPtr.Zero)
throw new System.ComponentModel.Win32Exception();
return hook;
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
if(MouseDown!=null)
MouseDown(null, new MSLLHOOKSTRUCTEventArgs(hookStruct));
}
else if (MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
{
if (MouseUp != null)
MouseUp(null, new MSLLHOOKSTRUCTEventArgs(hookStruct));
}
else
{
if (MouseMove != null)
MouseMove(null, new MSLLHOOKSTRUCTEventArgs(hookStruct));
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE = 7;
private const int WH_MOUSE_LL = 14;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
I'm using FlashWindowEx() to flash an application window when it needs to attract a user's attention. The window caption and taskbar button flashes continuously until the application receives focus. How can I check whether the application is currently flashing (i.e. has not received focus since it was instructed to flash).
Here are two possible solutions. One uses WH_SHELL, and one uses a NativeWindow. You will have to provide your own extension method (FlashWindow()) to start the flashing.
// base class. Two different forms subclass this form to illustrate two
// different solutions.
public class FormFlash : Form {
protected Label lb = new Label { Text = "Not flashing", Dock = DockStyle.Top };
public FormFlash() {
Controls.Add(lb);
Thread t = new Thread(() => {
Thread.Sleep(3000);
if (Form.ActiveForm == this)
SetForegroundWindow(GetDesktopWindow()); // deactivate the current form by setting the desktop as the foreground window
this.FlashWindow(); // call extension method to flash window
lb.BeginInvoke((Action) delegate {
lb.Text = "Flashing";
});
});
t.IsBackground = true;
t.Start();
}
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetDesktopWindow();
}
// this solution is a bit simpler. Relies on the programmer knowing when the
// flashing started. Uses a NativeWindow to detect when a WM_ACTIVATEAPP
// message happens, that signals the end of the flashing.
class FormFlashNW : FormFlash {
NW nw = null;
public FormFlashNW() {
}
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);
nw = new NW(this.Handle, lb);
}
protected override void OnHandleDestroyed(EventArgs e) {
base.OnHandleDestroyed(e);
nw.ReleaseHandle();
}
class NW : NativeWindow {
Label lb = null;
public NW(IntPtr handle, Label lb) {
AssignHandle(handle);
this.lb = lb;
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
const int WM_ACTIVATEAPP = 0x1C;
if (m.Msg == WM_ACTIVATEAPP) {
lb.BeginInvoke((Action) delegate {
lb.Text = "Not flashing";
});
}
}
}
}
// this solution is more complicated. Relies on setting up the hook proc.
// The 'isFlashing' bool fires true and false alternating while the flashing
// is active.
public class FormShellHook : FormFlash {
public FormShellHook() {
FlashWindowExListener.Register(this);
FlashWindowExListener.FlashEvent += FlashExListener_FlashEvent;
}
void FlashExListener_FlashEvent(Form f, bool isFlashing) {
if (f == this) {
lb.Text = DateTime.Now.ToLongTimeString() + " is flashing: " + isFlashing;
}
}
}
public class FlashWindowExListener {
private delegate IntPtr CallShellProc(int nCode, IntPtr wParam, IntPtr lParam);
private static CallShellProc procShell = new CallShellProc(ShellProc);
private static Dictionary<IntPtr,Form> forms = new Dictionary<IntPtr,Form>();
private static IntPtr hHook = IntPtr.Zero;
public static event FlashWindowExEventHandler FlashEvent = delegate {};
public delegate void FlashWindowExEventHandler(Form f, bool isFlashing);
static FlashWindowExListener() {
int processID = GetCurrentThreadId();
// we are interested in listening to WH_SHELL events, mainly the HSHELL_REDRAW event.
hHook = SetWindowsHookEx(WH_SHELL, procShell, IntPtr.Zero, processID);
System.Windows.Forms.Application.ApplicationExit += delegate {
UnhookWindowsHookEx(hHook);
};
}
public static void Register(Form f) {
if (f.IsDisposed)
throw new ArgumentException("Cannot use disposed form.");
if (f.Handle == IntPtr.Zero) {
f.HandleCreated += delegate {
forms[f.Handle] = f;
};
}
else
forms[f.Handle] = f;
f.HandleDestroyed += delegate {
Unregister(f);
};
}
public static void Unregister(Form f) {
forms.Remove(f.Handle);
}
private static IntPtr ShellProc(int nCode, IntPtr wParam, IntPtr lParam) {
if (nCode == HSHELL_REDRAW) {
Form f = null;
// seems OK not having to call f.BeginInvoke
if (forms.TryGetValue(wParam, out f))
FlashEvent(f, (int) lParam == 1);
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
private const int WH_SHELL = 10;
private const int HSHELL_REDRAW = 6;
[DllImport("user32.dll")]
private static extern int UnhookWindowsHookEx(IntPtr idHook);
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, CallShellProc lpfn, IntPtr hInstance, int threadId);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
}
I tried to use mouse_event() function, but it seems that it works asynchronously.
Below is my code (the problem is in Main method).
I set mouse position and simulate click, but my code returns the previous window (in the last line) even before click simulation happen.
How to overcome this asynchrony without suspending thread for 100 milliseconds?
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace MouseSimulatingTesting
{
class Program
{
static void Main(string[] args)
{
Thread.Sleep(3000); //just for testing - to have time to have an ability to switch to another window
//remember current foreground window
IntPtr previousForegroundWindow = GetForegroundWindow();
IntPtr browserWindowHandle = GetBrowserWindow();
//set browser window to foreground to make a click in it
ForceActivateWindow(browserWindowHandle);
//make a click
SetCursorPos(150, 20);
mouse_event(LEFT_DOWN, 0, 0, 0, 0);
mouse_event(LEFT_UP, 0, 0, 0, 0);
//Thread.Sleep(100); //if I uncomment this line then everything works perfectly
//return previous foreground window to top
ForceActivateWindow(browserWindowHandle);
}
const int LEFT_DOWN = 0x00000002;
const int LEFT_UP = 0x00000004;
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
[DllImport("user32.dll", EntryPoint = "SetCursorPos")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetCursorPos(int X, int Y);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll")]
public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool BringWindowToTop(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);
static public void ForceActivateWindow(IntPtr windowHandle)
{
uint processID;
uint foregroundThreadID = GetWindowThreadProcessId(GetForegroundWindow(), out processID);
uint mainThreadId = GetCurrentThreadId();
const uint SW_SHOW = 5;
if (foregroundThreadID != mainThreadId)
{
AttachThreadInput(foregroundThreadID, mainThreadId, true);
BringWindowToTop(windowHandle);
ShowWindow(windowHandle, SW_SHOW);
SetForegroundWindow(windowHandle);
AttachThreadInput(foregroundThreadID, mainThreadId, false);
}
else
{
BringWindowToTop(windowHandle);
ShowWindow(windowHandle, SW_SHOW);
SetForegroundWindow(windowHandle);
}
}
static IntPtr GetBrowserWindow()
{
var browserProcesses = Process.GetProcessesByName("opera");
if (browserProcesses.Length == 0)
throw new Exception("Browser is not opened");
return browserProcesses[0].MainWindowHandle;
}
}
}
I Wrote a short program in C# that monitors the clipboard. When a certain string enters the clipboard, a program must be opened with Process.Start (depending on the string). Everything works fine, but sometimes the application is being opened twice. I Don't know why this is happening.
namespace ClipboardMonitor {
public class Form1 : System.Windows.Forms.Form {
[DllImport("User32.dll")]
protected static extern int SetClipboardViewer(int hWndNewViewer);
[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
const int SW_SHOW = 5;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
IntPtr nextClipboardViewer;
private System.ComponentModel.Container components = null;
public Form1() {
InitializeComponent();
nextClipboardViewer = (IntPtr)SetClipboardViewer((int) this.Handle);
var handle = GetConsoleWindow();
ShowWindow(handle, SW_HIDE);
}
protected override void Dispose( bool disposing ) {
ChangeClipboardChain(this.Handle, nextClipboardViewer);
if( disposing ) {
if (components != null) {
components.Dispose();
}
}
base.Dispose( disposing );
}
private void InitializeComponent() {
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
this.Name = "Form1";
}
[STAThread]
static void Main() {
Application.Run(new Form1());
}
protected override void WndProc(ref System.Windows.Forms.Message m) {
const int WM_DRAWCLIPBOARD = 0x308;
const int WM_CHANGECBCHAIN = 0x030D;
switch(m.Msg) {
case WM_DRAWCLIPBOARD:
DisplayClipboardData();
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
break;
case WM_CHANGECBCHAIN:
if (m.WParam == nextClipboardViewer)
nextClipboardViewer = m.LParam;
else
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
break;
default:
base.WndProc(ref m);
break;
}
}
void DisplayClipboardData() {
Thread.Sleep(500);
try {
IDataObject iData = new DataObject();
iData = Clipboard.GetDataObject();
if (iData.GetDataPresent(DataFormats.Text)) {
string path = iData.GetData(DataFormats.Text).ToString();
string[] words = path.Split('_');
if (words[0] == "startLO") {
ProcessStartInfo info = new ProcessStartInfo(words[1]);
Process p = Process.Start(info);
}
} else {
// We doen niets.
}
}
catch(Exception e) {
MessageBox.Show(e.ToString());
}
}
}
One explanation would be that there are multiple clipboard events happening in rapid succession. This is fairly common. You can defend against this with a "settle time" delay. i.e. instead of reacting right away, set a timer or create a thread to handle it "in a little while". As more events come in, keep deferring the settletime. when the settletime finally expires, the timer or thread is allowed to actually run your program.