How to record while the window is not active? - c#

I am making a recorder that records a specific window the user chooses. While I am recording, the program forces the window to be active all the time. It does not let me minimize it or even move it. It forced me to use alt + f4(that kills the active window) because I was not able to stop the recording. Is there a way to fix that?
Combobox code:
private void Handlebox_SelectedIndexChanged(object sender, EventArgs e)
{
if (Handlebox.SelectedIndex == 0)
{
handle_name = Handlebox.Items[0].ToString();
}
else if (Handlebox.SelectedIndex == 1)
{
handle_name = Handlebox.Items[1].ToString();
}
else if (Handlebox.SelectedIndex == 2)
{
handle_name = Handlebox.Items[2].ToString();
}
else if (Handlebox.SelectedIndex == 3)
{
handle_name = Handlebox.Items[3].ToString();
}
else if (Handlebox.SelectedIndex == 4)
{
handle_name = Handlebox.Items[4].ToString();
}
else if (Handlebox.SelectedIndex == 5)
{
handle_name = Handlebox.Items[5].ToString();
}
}
The way I add all the processes in the combobox:
foreach (Process process in processlist)
{
if (!String.IsNullOrEmpty(process.MainWindowTitle))
{
Handlebox.Items.Add(process.ProcessName);
}
}
The script that the whole recording takes place:
// Record video:
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hWnd);
private const int SW_RESTORE = 9;
[DllImport("user32.dll")]
private static extern IntPtr ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
public Bitmap CaptureApplication(string procName)
{
Process proc;
// Cater for cases when the process can't be located.
try
{
proc = Process.GetProcessesByName(procName)[0];
}
catch (IndexOutOfRangeException e)
{
return null;
}
// You need to focus on the application
SetForegroundWindow(proc.MainWindowHandle);
ShowWindow(proc.MainWindowHandle, SW_RESTORE);
// Delay
Thread.Sleep(1000);
Rect rect = new Rect();
IntPtr error = GetWindowRect(proc.MainWindowHandle, ref rect);
// sometimes it gives error.
while (error == (IntPtr)0)
{
error = GetWindowRect(proc.MainWindowHandle, ref rect);
}
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Graphics.FromImage(bmp).CopyFromScreen(rect.left,rect.top,0,0,new Size(width, height),CopyPixelOperation.SourceCopy);
return bmp;
}
public void RecordVideo()
{
// Keep track of time:
watch.Start();
// Save screenshot:
string name = tempPath + "//screenshot-" + fileCount + ".png";
CaptureApplication(handle_name).Save(name, ImageFormat.Png);
inputImageSequence.Add(name);
fileCount++;
// Dispose of bitmap:
CaptureApplication(handle_name).Dispose();
}

Apologies for the brevity and style of this reply; I'm currently on mobile.
Could you express your combobox event handler as:
private void Handlebox_SelectedIndexChanged(object sender, EventArgs e)
{
if (Handlebox.SelectedIndex == -1) return;
handle_name = Handlebox.SelectedItem.ToString();
}
I'm not sure what exactly you want this application to do eventually, but If all you want is to gracefully exit, I would look into registering an event handler that watches for a key combination, and stops and saves the recording when it is pressed. I can't easily type out how to do that, but some concerted googling should help you.

Related

C# Camera Capture with AviCap32.dll

I'm trying to capture images from my webcam by using avicap32.dll. An event should be called when a new image is available. The problem is that it only shows a black image with a few rows of colored pixels at the bottom (Sample image).
I DON'T want to use any other libraries like Aforge, DirectShow, OpenCV or something similar.
Here is my code:
public class CameraCapture2
{
[DllImport("user32", EntryPoint = "SendMessage")]
static extern bool SendMessage(int hWnd, uint wMsg, int wParam, int lParam);
[DllImport("user32", EntryPoint = "SendMessage")]
static extern int SendBitmapMessage(int hWnd, uint wMsg, int wParam, ref BITMAPINFO lParam);
[DllImport("user32", EntryPoint = "SendMessage")]
static extern int SendHeaderMessage(int hWnd, uint wMsg, int wParam, CallBackDelegate lParam);
[DllImport("avicap32.dll", EntryPoint = "capCreateCaptureWindow")]
static extern int capCreateCaptureWindow(string lpszWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, int hwndParent, int nID);
delegate void CallBackDelegate(IntPtr hwnd, ref VIDEOHEADER hdr);
CallBackDelegate delegateFrameCallBack;
AutoResetEvent autoEvent = new AutoResetEvent(false);
Thread frameThread;
public event EventHandler<NewFrameEventArgs> NewFrame;
public int FPS = 0;
public const int BitsPerPixel = 24; //RGB (by changing this value, change the other PixelFormats)
public int frameWidth = 0;
public int frameHeight = 0;
public int camID = 0;
int camHwnd, parentHwnd;
bool bStart = false;
object threadLock = new object();
int preferredFPSms;
public CameraCapture2(int frameWidth, int frameHeight, int preferredFPS, int camID, int parentHwnd)
{
this.frameWidth = frameWidth;
this.frameHeight = frameHeight;
this.parentHwnd = parentHwnd;
this.camID = camID;
PreferredFPS = preferredFPS;
delegateFrameCallBack = FrameCallBack;
}
public void Start()
{
try
{
camHwnd = capCreateCaptureWindow("WebCam", 0, 0, 0, frameWidth, frameHeight, parentHwnd, camID);
// connect to the device
if (SendMessage(camHwnd, WM_CAP.WM_CAP_DRIVER_CONNECT, 0, 0))
{
BITMAPINFO bInfo = new BITMAPINFO();
bInfo.bmiHeader = new BITMAPINFOHEADER();
bInfo.bmiHeader.biSize = (uint)Marshal.SizeOf(bInfo.bmiHeader);
bInfo.bmiHeader.biWidth = frameWidth;
bInfo.bmiHeader.biHeight = frameHeight;
bInfo.bmiHeader.biPlanes = 1;
bInfo.bmiHeader.biBitCount = BitsPerPixel; // bits per pixel, 24 - RGB
//Enable preview mode. In preview mode, frames are transferred from the
//capture hardware to system memory and then displayed in the capture
//window using GDI functions.
SendMessage(camHwnd, WM_CAP.WM_CAP_SET_PREVIEW, 1, 0);
SendMessage(camHwnd, WM_CAP.WM_CAP_SET_PREVIEWRATE, 34, 0); // sets the frame display rate in preview mode
SendBitmapMessage(camHwnd, WM_CAP.WM_CAP_SET_VIDEOFORMAT, Marshal.SizeOf(bInfo), ref bInfo);
frameThread = new Thread(new ThreadStart(this.FrameGrabber));
bStart = true; // First, set variable
frameThread.Priority = ThreadPriority.Lowest;
frameThread.Start(); // Only then put thread to the queue
}
else
throw new Exception("Cannot connect to device");
}
catch (Exception e)
{
Stop();
throw new Exception("Error: " + e.Message);
}
}
public void Stop()
{
try
{
bStart = false;
Set();
SendMessage(camHwnd, WM_CAP.WM_CAP_DRIVER_DISCONNECT, 0, 0);
}
catch { }
}
private void FrameGrabber()
{
while (bStart) // if worker active thread is still required
{
try
{
// get the next frame. This is the SLOWEST part of the program
SendMessage(camHwnd, WM_CAP.WM_CAP_GRAB_FRAME_NOSTOP, 0, 0);
SendHeaderMessage(camHwnd, WM_CAP.WM_CAP_SET_CALLBACK_FRAME, 0, delegateFrameCallBack);
}
catch (Exception excep)
{
this.Stop(); // stop the process
throw new Exception("Capturing error:\r\n" + excep.Message);
}
}
}
/// <summary>
/// Allow waiting worker (FrameGrabber) thread to proceed
/// </summary>
public void Set()
{
autoEvent.Set();
}
private void FrameCallBack(IntPtr hwnd, ref VIDEOHEADER hdr)
{
if (NewFrame != null)
{
//Bitmap bmp = new Bitmap(frameWidth, frameHeight, frameWidth * 3, System.Drawing.Imaging.PixelFormat.Format24bppRgb, hdr.lpData);
byte[] _imageTemp = new byte[hdr.dwBufferLength];
Marshal.Copy(hdr.lpData, _imageTemp, 0, (int)hdr.dwBufferLength);
Bitmap bmp = new Bitmap(new System.IO.MemoryStream(WriteBitmapFile(frameWidth, frameHeight, _imageTemp)));
NewFrame(this, new NewFrameEventArgs(bmp));
}
// block thread for preferred milleseconds
if (preferredFPSms == 0)
autoEvent.WaitOne();
else
autoEvent.WaitOne(preferredFPSms, false);
}
private static byte[] WriteBitmapFile(int width, int height, byte[] imageData)
{
using (var stream = new System.IO.MemoryStream(imageData))
using (var bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
{
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height)
, System.Drawing.Imaging.ImageLockMode.WriteOnly
, bmp.PixelFormat
);
Marshal.Copy(imageData, 0, bmpData.Scan0, imageData.Length);
bmp.UnlockBits(bmpData);
if (bmp == null)
return null;
bmp.RotateFlip(RotateFlipType.Rotate180FlipNone);
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png); // get bitmap bytes
return ms.ToArray();
} // End Using stream
}
}
public void ShowVideoDialog()
{
SendMessage(camHwnd, WM_CAP.WM_CAP_DLG_VIDEODISPLAY, 0, 0);
}
public int PreferredFPS
{
get { return 1000 / preferredFPSms; }
set
{
if (value == 0)
preferredFPSms = 0;
else if (value > 0 && value <= 30)
{
preferredFPSms = 1000 / value;
}
}
}
}
public class NewFrameEventArgs
{
public Bitmap Frame;
public NewFrameEventArgs(Bitmap frame)
{
Frame = frame;
}
}
Most of this code is from Codeproject

DateTimePicker control in ContextMenuStrip

I have added a DateTimePicker in ContextMenuStrip using ToolStripControlHost. I am using below code.
DateTimePicker startDate = new DateTimePicker();
(cms.Items["mnuStartDate"] as ToolStripMenuItem).DropDownItems.Add(new ToolStripControlHost(startDate));
Selecting of date is working but when I clicked on the arrows to go to the previous or next month, or if I clicked on the Month, the ToolStrip is closing. Is there any workaround here? Thanks.
Note: I am showing the cms(ContextMenuStrip ) when Right Clicking on a control.
Looks like the ToolStrip behavior closes when an item is selected. So I juts used CalendarMonth Control as a replacement. Link here
It seems to be related to Application.EnableVisualStyles(); When not-enabled, the menu doesn't unexpectedly close.
When enabled, to prevent closing, detect if the CalendarMonth menu is currently visible, and if the mouse was clicked on it.
public class DatePicker : DateTimePicker {
private const int DtmFirst = 0x1000;
private const int DtmGetmonthcal = (DtmFirst + 8);
private bool isDroppedDown = false;
private IntPtr hwndCalendarWindow = IntPtr.Zero;
protected override void OnDropDown(EventArgs e) {
isDroppedDown = true;
hwndCalendarWindow = SendMessage(Handle, DtmGetmonthcal, 0, 0);
base.OnDropDown(e);
}
protected override void OnCloseUp(EventArgs eventargs) {
isDroppedDown = false;
base.OnCloseUp(eventargs);
}
public bool CalendarMonthClicked(Point pt) {
if (!isDroppedDown)
return false;
RECT r = new RECT();
GetWindowRect(hwndCalendarWindow, out r);
return pt.X >= r.Left && pt.X <= r.Right && pt.Y >= r.Top && pt.Y <= r.Bottom;
}
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("User32.dll")]
private static extern IntPtr SendMessage(IntPtr h, int msg, int param, int data);
[StructLayout(LayoutKind.Sequential)]
private struct RECT {
public int Left, Top, Right, Bottom;
}
}
static class Program {
//[DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
//public extern static Int32 SetWindowTheme(IntPtr hWnd, String textSubAppName, String textSubIdList);
[STAThread]
static void Main() {
Application.EnableVisualStyles(); // if you disable visual styles then the menu won't close
DatePicker dpStart = new DatePicker();
dpStart.MinimumSize = new Size(100, 50);
Form ff = new Form();
ContextMenuStrip cms = new ContextMenuStrip();
ToolStripMenuItem menu = new ToolStripMenuItem("Menu");
menu.DropDown.Closing += (o, e) => {
e.Cancel = (e.CloseReason == ToolStripDropDownCloseReason.AppClicked && dpStart.CalendarMonthClicked(Cursor.Position));
};
// sub-menu doesn't close properly, probably related to the ToolStripControlHost
cms.Opening += delegate {
menu.DropDown.Close(ToolStripDropDownCloseReason.CloseCalled);
};
cms.Closed += delegate {
menu.DropDown.Close(ToolStripDropDownCloseReason.CloseCalled);
};
ff.ContextMenuStrip = cms;
cms.Items.Add(menu);
ToolStripControlHost item = new ToolStripControlHost(dpStart) { AutoSize = true };
menu.DropDownItems.Add(item);
Application.Run(ff);
}
}

Embed Unity3D app inside WPF page causes process name to disappear after navigating to new page

I am using the code posted in this question with some minor changes:
Embed Unity3D app inside WPF *without* having it take up the whole window
This approach worked great, but when I am looking at my task manager processes. My main WPF executable name is removed from the process when I exit the page running the unity player and load another page. The application still works just fine. Task Manager just shows an icon with no process name next to it. This is only an issue because I have another background service that monitor my WPF application and starts and stops it remotely based on its name. Any suggestion?
Page Code Shown Below.
public System.Windows.Forms.Integration.WindowsFormsHost host = new System.Windows.Forms.Integration.WindowsFormsHost();
[DllImport("User32.dll")]
static extern bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw);
internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
[DllImport("user32.dll")]
internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);
[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
private Process process;
private IntPtr unityHWND = IntPtr.Zero;
private const int WM_ACTIVATE = 0x0006;
private readonly IntPtr WA_ACTIVE = new IntPtr(1);
private readonly IntPtr WA_INACTIVE = new IntPtr(0);
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
bool initialized = false;
public UnityPlayer()
{
InitializeComponent();
if (this.grid1.Children.Count == 0)
{
this.grid1.Children.Add(host);
}
dispatcherTimer.Tick += attemptInit;
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
}
void attemptInit(object sender, EventArgs e)
{
if (process != null)
{
if (process.HasExited)
{
Thread.Sleep(1000);
FSC.GoHome();
}
}
if (initialized)
return;
HwndSource source = (HwndSource)HwndSource.FromVisual(host);
Console.WriteLine("attempting to get handle...");
if (source == null)
{
Console.WriteLine("Failed to get handle source");
return;
}
IntPtr hWnd = source.Handle;
try
{
process = new Process();
process.StartInfo.FileName = "Block Breaker.exe";
process.StartInfo.Arguments = "-parentHWND " + hWnd.ToInt32() + " " + Environment.CommandLine;
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
process.WaitForInputIdle();
// Doesn't work for some reason ?!
//unityHWND = process.MainWindowHandle;
EnumChildWindows(host.Handle, WindowEnum, IntPtr.Zero);
//unityHWNDLabel.Text = "Unity HWND: 0x" + unityHWND.ToString("X8");
Console.WriteLine("Unity HWND: 0x" + unityHWND.ToString("X8"));
panel1_Resize(this, EventArgs.Empty);
initialized = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + ".\nCheck if Container.exe is placed next to UnityGame.exe.");
}
}
private void ActivateUnityWindow()
{
SendMessage(unityHWND, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero);
}
private void DeactivateUnityWindow()
{
SendMessage(unityHWND, WM_ACTIVATE, WA_INACTIVE, IntPtr.Zero);
}
private int WindowEnum(IntPtr hwnd, IntPtr lparam)
{
unityHWND = hwnd;
ActivateUnityWindow();
return 0;
}
private void panel1_Resize(object sender, EventArgs e)
{
MoveWindow(unityHWND, 0, 0, (int)host.Width, (int)host.Height, true);
Console.WriteLine("RESIZED UNITY WINDOW TO: " + (int)host.Width + "x" + (int)host.Height);
ActivateUnityWindow();
}
private void Page_Unloaded(object sender, RoutedEventArgs e)
{
dispatcherTimer.Stop();
dispatcherTimer = null;
host.Dispose();
}
Image Show Process Before the pages loads
Image show Process While the page is running
Image show Process After the pages exits and loads new page

How to Disable Autoscrolling in richtextbox in c#

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!

Taskbar location

How can i detect where the taskbar is located? I need to know for displaying my notification in the right corner. Thanks
Edit:
Thank you Hans Passant. I used that with this to get location. I hope is ok.
GetTaskbarLocation(TaskbarPosition.GetTaskbarPosition());
private void GetTaskbarLocation(Rectangle rc)
{
if (rc.X == rc.Y)
{
if (rc.Right < rc.Bottom)
taskbarLocation = TaskbarLocation.Left;
if (rc.Right > rc.Bottom)
taskbarLocation = TaskbarLocation.Top;
}
if (rc.X > rc.Y)
taskbarLocation = TaskbarLocation.Right;
if (rc.X < rc.Y)
taskbarLocation = TaskbarLocation.Bottom;
}
public static Rectangle GetTaskbarPosition() {
var data = new APPBARDATA();
data.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(data);
IntPtr retval = SHAppBarMessage(ABM_GETTASKBARPOS, ref data);
if (retval == IntPtr.Zero) throw new Win32Exception("Please re-install Windows");
return new Rectangle(data.rc.left, data.rc.top,
data.rc.right - data.rc.left, data.rc.bottom - data.rc.top);
}
// P/Invoke goo:
private const int ABM_GETTASKBARPOS = 5;
[System.Runtime.InteropServices.DllImport("shell32.dll")]
private static extern IntPtr SHAppBarMessage(int msg, ref APPBARDATA data);
private struct APPBARDATA {
public int cbSize;
public IntPtr hWnd;
public int uCallbackMessage;
public int uEdge;
public RECT rc;
public IntPtr lParam;
}
private struct RECT {
public int left, top, right, bottom;
}
SHAppBarMessage(ABM_GETTASKBARPOS)
See the SHAppBarMessage Function and the ABM_GETTASKBARPOS Message for more info and the pinvoke page for SHAppBarMessage has a VB.Net sample that shouldn't be too difficult to translate.
The SHAppBarMessage function will return you information about the taskbar if you pass in the ABM_GETTASKBARPOS message. It has an out parameter which is a pointer to APPBARDATA that contains the screen cooridinates of the task bar. You can use to work out where on screen it is.
It's probably best to use the available API: NotifyIcon.ShowBalloonTip:
void Form1_DoubleClick(object sender, EventArgs e)
{
notifyIcon1.Visible = true;
notifyIcon1.ShowBalloonTip(20000, "Information", "This is the text",
ToolTipIcon.Info );
}
In Java, using JNA (adapted from other C# solutions above)
public static Rectangle getTaskbarPosition() throws Exception {
APPBARDATA data = new APPBARDATA();
data.cbSize = new WinDef.DWORD(data.size());
WinDef.UINT_PTR retval = Shell32.INSTANCE.SHAppBarMessage(ABM_GETTASKBARPOS, data);
if (retval == null) {
throw new Exception("Please re-install Windows");
}
return new Rectangle(data.rc.left, data.rc.top, data.rc.right - data.rc.left, data.rc.bottom - data.rc.top);
}

Categories