I written a Kiosk style C# application using visual studio that is run on startup and should expand to full-screen and cover the task-bar.
I am doing the usual setting boarder style to none, and fill extents and it works perfectly if I just launch the application manually.
When the application launches on startup (by way of a short-cut in the startup folder in the start menu), the task-bar ends up on top of the program and clicking somewhere on the form does not bring the form back to the top.
Has anyone encountered this problem before, or know of possible workarounds.
I have also done this another time:
public class Screensize
{
/// <summary>
/// Selected Win AI Function Calls
/// </summary>
public class WinApi
{
[DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
public static extern int GetSystemMetrics(int which);
[DllImport("user32.dll")]
public static extern void
SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter,
int X, int Y, int width, int height, uint flags);
private const int SM_CXSCREEN = 0;
private const int SM_CYSCREEN = 1;
private static IntPtr HWND_TOP = IntPtr.Zero;
private const int SWP_SHOWWINDOW = 64; // 0x0040
public static int ScreenX
{
get { return GetSystemMetrics(SM_CXSCREEN); }
}
public static int ScreenY
{
get { return GetSystemMetrics(SM_CYSCREEN); }
}
public static void SetWinFullScreen(IntPtr hwnd)
{
SetWindowPos(hwnd, HWND_TOP, 0, 0, ScreenX, ScreenY, SWP_SHOWWINDOW);
}
}
/// <summary>
/// Class used to preserve / restore state of the form
/// </summary>
public class FormState
{
private FormWindowState winState;
private FormBorderStyle brdStyle;
private bool topMost;
private Rectangle bounds;
private bool IsMaximized = false;
public void Maximize(Form targetForm)
{
if (!IsMaximized)
{
IsMaximized = true;
Save(targetForm);
targetForm.WindowState = FormWindowState.Maximized;
targetForm.FormBorderStyle = FormBorderStyle.None;
targetForm.TopMost = false;
WinApi.SetWinFullScreen(targetForm.Handle);
}
}
public void Save(Form targetForm)
{
winState = targetForm.WindowState;
brdStyle = targetForm.FormBorderStyle;
topMost = targetForm.TopMost;
bounds = targetForm.Bounds;
}
public void Restore(Form targetForm)
{
targetForm.WindowState = winState;
targetForm.FormBorderStyle = brdStyle;
targetForm.TopMost = topMost;
targetForm.Bounds = bounds;
IsMaximized = false;
}
}
and just call in your form:
screensize.Maximize(this)
I think you mean this
And now I see this post is from 2013...
Workaround: When starting, kill explorer.exe - you don't need it -> taskbar disappear.
When needed, start it using Task Manager
Related
I have a border-less windows form that i created a shadow behind it using the code below.
However when I click on the parent form the shadow disappears.
can anyone help me out on how to keep the shadow even when clicking on anther form/parent form?
The shaddow is visable against a diffrent window (chrome for example) but not against it's parent form
(I tried google but couldn't find anything)
Update
I do notice that if i minimize the window and maximize it again the shadow does come back
My Code
private const int CS_DROPSHADOW = 0x00020000;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ClassStyle |= CS_DROPSHADOW;
return cp;
}
}
Thanks in advance
Pls try the below steps and revert back for any errors:
Add the below code to a new code file named DropShadow.cs;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Core
{
public class DropShadow
{
#region Shadowing
#region Fields
private bool _isAeroEnabled = false;
private bool _isDraggingEnabled = false;
private const int WM_NCHITTEST = 0x84;
private const int WS_MINIMIZEBOX = 0x20000;
private const int HTCLIENT = 0x1;
private const int HTCAPTION = 0x2;
private const int CS_DBLCLKS = 0x8;
private const int CS_DROPSHADOW = 0x00020000;
private const int WM_NCPAINT = 0x0085;
private const int WM_ACTIVATEAPP = 0x001C;
#endregion
#region Structures
[EditorBrowsable(EditorBrowsableState.Never)]
public struct MARGINS
{
public int leftWidth;
public int rightWidth;
public int topHeight;
public int bottomHeight;
}
#endregion
#region Methods
#region Public
[DllImport("dwmapi.dll")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);
[DllImport("dwmapi.dll")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
[DllImport("dwmapi.dll")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static extern int DwmIsCompositionEnabled(ref int pfEnabled);
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool IsCompositionEnabled()
{
if (Environment.OSVersion.Version.Major < 6) return false;
bool enabled;
DwmIsCompositionEnabled(out enabled);
return enabled;
}
#endregion
#region Private
[DllImport("dwmapi.dll")]
private static extern int DwmIsCompositionEnabled(out bool enabled);
[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
private static extern IntPtr CreateRoundRectRgn
(
int nLeftRect,
int nTopRect,
int nRightRect,
int nBottomRect,
int nWidthEllipse,
int nHeightEllipse
);
private bool CheckIfAeroIsEnabled()
{
if (Environment.OSVersion.Version.Major >= 6)
{
int enabled = 0;
DwmIsCompositionEnabled(ref enabled);
return (enabled == 1) ? true : false;
}
return false;
}
#endregion
#region Overrides
public void ApplyShadows(Form form)
{
var v = 2;
DwmSetWindowAttribute(form.Handle, 2, ref v, 4);
MARGINS margins = new MARGINS()
{
bottomHeight = 1,
leftWidth = 0,
rightWidth = 0,
topHeight = 0
};
DwmExtendFrameIntoClientArea(form.Handle, ref margins);
}
#endregion
#endregion
#endregion
}
}
In your form, add this line below InitializeComponent();
(new Core.DropShadow()).ApplyShadows(this);
I am attempting to overlay a status message on an external application.
Previously, I achieved this by using a TransparencyKey on a Form and the following API call to get the window location with a hook to capture the window moved event.
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hWnd, ref Rect lpRect);
This works on my development machine, however, on the target machine it fails, the transparent area actually has hatch markings over it. Presumably something to do with that machine being a VM and having no hardware graphics accelleration.
So, I've done away with the Form and have the following code (with DrawFrame() being called every 60ms) to draw manually to the screen:
class DirectDisplay:IDisposable
{
private Graphics window;
private SolidBrush b;
private string Status;
private NativeMethods.Rect location;
private bool running;
public DirectDisplay(IntPtr _targetHWnd, string status)
{
Status = status;
b = new SolidBrush(Color.FromArgb(255,0,149,48));
window = Graphics.FromHwnd(_targetHWnd);
}
public void DrawFrame()
{
window.DrawString(Status, new Font("Arial", 12),b, 0, -20);
}
public void Dispose()
{
window?.Dispose();
b?.Dispose();
}
}
Which works fine:
However, I need to be able to draw up here on the title bar:
It appears as though utilising Graphics.FromHwnd() limits me to using the typeable space in notepad so I can't draw directly into the button bar.
How do I get a graphics object encompassing the entire Window that I can draw over?
For reference, here is the rest of my code:
namespace OnScreenOverlay
{
class DataManager:IDisposable
{
private const string USER_CACHE = #"C:\test.txt";
private DirectDisplay directDisplay;
private volatile bool exiting;
private readonly Process _target;
private readonly IntPtr _targetHWnd;
private string _currentUser;
private int _daysUntilExpiry;
private NativeMethods.Rect _location;
public DataManager()
{
_target= Process.GetProcessesByName("notepad")[0];
if (_target== null)
{
MessageBox.Show("No target detected... Closing");
}
_targetHWnd = _target.MainWindowHandle;
//InitializeWinHook();
GetCurrentUser();
GetExpiryDate();
directDisplay = new DirectDisplay(_targetHWnd, $"Current User: {_currentUser} --- Password Expires: {_daysUntilExpiry} days");
}
private void GetCurrentUser()
{
if (File.Exists(USER_CACHE))
{
_currentUser = File.ReadAllLines(USER_CACHE)[0].Split('=')[0];
}
else
{
Application.Exit();
}
}
private void GetExpiryDate()
{
using (PrincipalContext domain = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal user = UserPrincipal.FindByIdentity(domain, IdentityType.SamAccountName, _currentUser))
{
DateTime? pwLastSet = user?.LastPasswordSet;
if (pwLastSet.HasValue)
{
_daysUntilExpiry = (int)(TimeSpan.FromDays(7) - (DateTime.Now - pwLastSet.Value)).TotalDays;
}
else
{
_daysUntilExpiry = int.MinValue;
}
}
}
}
public void Start()
{
while (!exiting)
{
directDisplay.DrawFrame();
Thread.Sleep(1000/60); //Prevent method returning
}
}
private void InitializeWinHook()
{
NativeMethods.SetWinEventHook(NativeMethods.EVENT_OBJECT_LOCATIONCHANGE, NativeMethods.EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, TargetMoved, (uint)_target.Id,
NativeMethods.GetWindowThreadProcessId(_target.MainWindowHandle, IntPtr.Zero), NativeMethods.WINEVENT_OUTOFCONTEXT | NativeMethods.WINEVENT_SKIPOWNPROCESS | NativeMethods.WINEVENT_SKIPOWNTHREAD);
}
private void TargetMoved(IntPtr hWinEventHook, uint eventType, IntPtr lParam, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
NativeMethods.GetWindowRect(_targetHWnd, ref _location);
}
public void Dispose()
{
directDisplay?.Dispose();
_target?.Dispose();
}
}
}
I realise that I don't need the WindowsHook stuff if I'm utilising this method to get the Graphics object, I just haven't removed it yet in-case this method doesn't work.
Further to this, I know I could get the Graphics object for the Desktop using IntPtr.Zero but I only want my overlay to be a Single Z-level above the target application.
Is there an easy method to restore a minimized form to its previous state, either Normal or Maximized? I'm expecting the same functionality as clicking the taskbar (or right-clicking and choosing restore).
So far, I have this, but if the form was previously maximized, it still comes back as a normal window.
if (docView.WindowState == FormWindowState.Minimized)
docView.WindowState = FormWindowState.Normal;
Do I have to handle the state change in the form to remember the previous state?
I use the following extension method:
using System.Runtime.InteropServices;
namespace System.Windows.Forms
{
public static class Extensions
{
[DllImport( "user32.dll" )]
private static extern int ShowWindow( IntPtr hWnd, uint Msg );
private const uint SW_RESTORE = 0x09;
public static void Restore( this Form form )
{
if (form.WindowState == FormWindowState.Minimized)
{
ShowWindow(form.Handle, SW_RESTORE);
}
}
}
}
Then call form.Restore() in my code.
The easiest way to restore a form to normal state is:
if (MyForm.WindowState == FormWindowState.Minimized)
{
MyForm.WindowState = FormWindowState.Normal;
}
You could simulate clicking on the taskbar button like this:
SendMessage(docView.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
For me, the code above does NOT work.
But at last I found the working code. Here it is:
CxImports.ManagedWindowPlacement placement = new CxImports.ManagedWindowPlacement();
CxImports.GetWindowPlacement(Convert.ToUInt32(Handle.ToInt64()), placement);
if (placement.flags == CxImports.WPF_RESTORETOMAXIMIZED)
WindowState = FormWindowState.Maximized;
else
WindowState = FormWindowState.Normal;
I guess, you can find all the needed "imported" functions by simple googling.
If anybody wonders how to do that with other apps windows,this code works for me:
public void UnMinimize(IntPtr handle)
{
WINDOWPLACEMENT WinPlacement = new WINDOWPLACEMENT();
GetWindowPlacement(handle, out WinPlacement);
if(WinPlacement.flags.HasFlag(WINDOWPLACEMENT.Flags.WPF_RESTORETOMAXIMIZED))
{
ShowWindow(handle, (int)SW_MAXIMIZE);
}
else
{
ShowWindow(handle, (int)SW_RESTORE);
}
}
Stuff is here:
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public Int32 Left;
public Int32 Top;
public Int32 Right;
public Int32 Bottom;
}
public struct POINT
{
public int x;
public int y;
}
public struct WINDOWPLACEMENT
{
[Flags]
public enum Flags : uint
{
WPF_ASYNCWINDOWPLACEMENT = 0x0004,
WPF_RESTORETOMAXIMIZED = 0x0002,
WPF_SETMINPOSITION = 0x0001
}
/// <summary>
/// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT).
/// </summary>
public uint length;
/// <summary>
/// The flags that control the position of the minimized window and the method by which the window is restored. This member can be one or more of the following values.
/// </summary>
///
public Flags flags;//uint flags;
/// <summary>
/// The current show state of the window. This member can be one of the following values.
/// </summary>
public uint showCmd;
/// <summary>
/// The coordinates of the window's upper-left corner when the window is minimized.
/// </summary>
public POINT ptMinPosition;
/// <summary>
/// The coordinates of the window's upper-left corner when the window is maximized.
/// </summary>
public POINT ptMaxPosition;
/// <summary>
/// The window's coordinates when the window is in the restored position.
/// </summary>
public RECT rcNormalPosition;
}
public class UnMinimizeClass
{
[DllImport("user32.dll")]
public static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_MAXIMIZE = 3;
const int SW_RESTORE = 9;
public static void UnMinimize(IntPtr handle)
{
WINDOWPLACEMENT WinPlacement = new WINDOWPLACEMENT();
GetWindowPlacement(handle, out WinPlacement);
if (WinPlacement.flags.HasFlag(WINDOWPLACEMENT.Flags.WPF_RESTORETOMAXIMIZED))
{
ShowWindow(handle, SW_MAXIMIZE);
}
else
{
ShowWindow(handle, (int)SW_RESTORE);
}
}
}
Using MainWindow.WindowState = WindowState.Normal; isn't enough
Next approach works for my WPF applcation:
MainWindow.WindowState = WindowState.Normal;
MainWindow.Show();
MainWindow.Activate();
I just added one more piece to generify the solution given by #Mesmo. It will create the instance if not created or restore and focus the form if the instance is already created from anywhere in the application. My requirement was that I didn't want to open multiple forms for some of the functionality in the application.
Utilities Class:
public static class Utilities
{
[DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hWnd, uint Msg);
private const uint SW_RESTORE = 0x09;
public static void Restore(this Form form)
{
if (form.WindowState == FormWindowState.Minimized)
{
ShowWindow(form.Handle, SW_RESTORE);
}
}
public static void CreateOrRestoreForm<T>() where T: Form
{
Form form = Application.OpenForms.OfType<T>().FirstOrDefault();
if (form == null)
{
form = Activator.CreateInstance<T>();
form.Show();
}
else
{
form.Restore();
form.Focus();
}
}
}
Usage:
Utilities.CreateOrRestoreForm<AboutForm>();
This is simple and works if you don't want to use any PInvoke or API trickery. Keep track of when the form has been resized, ignoring when it is minimised.
FormWindowState _PreviousWindowState;
private void TestForm_Resize(object sender, EventArgs e)
{
if (WindowState != FormWindowState.Minimized)
_PreviousWindowState = WindowState;
}
Later when you want to restore it -- for example if a tray icon is clicked:
private void Tray_MouseClick(object sender, MouseEventArgs e)
{
Activate();
if (WindowState == FormWindowState.Minimized)
WindowState = _PreviousWindowState; // former glory
}
[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr hWnd, ref wndRect lpRect);
[DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")] public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);//用来遍历所有窗口
[DllImport("user32.dll")] public static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);//获取窗口Text
[DllImport("user32.dll")] public static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);//获取窗口类名
public static List<wndInfo> GetAllDesktopWindows(bool? isVisitable_)
{
//用来保存窗口对象
List<wndInfo> wndList = new List<wndInfo>();
//enum all desktop windows
EnumWindows(delegate (IntPtr hWnd, int lParam)
{
wndInfo wnd = new wndInfo();
StringBuilder sb = new StringBuilder(256);
//get hwnd
wnd.hWnd = hWnd;
if (isVisitable_ == null || IsWindowVisible(wnd.hWnd) == isVisitable_)
{
//get window name
GetWindowTextW(hWnd, sb, sb.Capacity);
wnd.szWindowName = sb.ToString();
//get window class
GetClassNameW(hWnd, sb, sb.Capacity);
wnd.szClassName = sb.ToString();
wndList.Add(wnd);
}
return true;
}, 0);
return wndList;
}
private void Btn_Test5_Click(object sender, RoutedEventArgs e)
{
var ws = WSys.GetAllDesktopWindows(true);
foreach (var w in ws)
{
if (w.szWindowName == "计算器")
{
WSys.ShowWindow(w.hWnd, 5);
WSys.ShowWindow(w.hWnd, 9);
Log.WriteLine(w.szWindowName);
}
}
}
The above code did not quite work for me in all situations
After checking the flags I also have to check showcmd=3 and if so maximise else restore
Hi I'm developing an application that parsing data then after that I want to visualize some data on map using MapInfo, I made a MapInfo instance correctly but till now I do not know how to display data on the instance or how to use it also the instance I've created is not visible even after I make visible.
below is my code
namespace JA3_Trace_Viewer
{
public partial class JA3Main : Form
{
public JA3Main()
{
InitializeComponent();
}
private void JA3Main_Load(object sender, EventArgs e)
{
MapInfo.MapInfoApplication mapinfoinstance = new MapInfo.MapInfoApplication();
mapinfoinstance.Visible = true;
DDockWindow winM = new DDockWindow();
winM.Activate();
}
}
The data that I want to visualize on map is longitude and latitude and another columns lets call them data, so please if you help me.
Thanks in advance.
The new code:
public partial class Form1 : Form
{
// Sets the parent of a window.
[DllImport("User32", CharSet = CharSet.Auto, ExactSpelling = true)]
internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);
//Sets window attributes
[DllImport("USER32.DLL")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
//Gets window attributes
[DllImport("USER32.DLL")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
//assorted constants needed
public static int GWL_STYLE = -16;
public static int WS_CHILD = 0x40000000; //child window
public static int WS_BORDER = 0x00800000; //window with border
public static int WS_DLGFRAME = 0x00400000; //window with double border but no title
public static int WS_CAPTION= WS_BORDER | WS_DLGFRAME; //window with a title bar
public static int WS_MAXIMIZE = 0x1000000;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Create a new instance of MapInfo.
MapInfoApplication mapinfo = new MapInfoApplication();
// Get the handle to the whole MapInfo application.
// 9 = SYS_INFO_MAPINFOWND.
string handle = mapinfo.Eval("SystemInfo(9)");
// Convert the handle to an IntPtr type.
IntPtr oldhandle = new IntPtr(Convert.ToInt32(handle));
//Make mapinfo visible otherwise it won't show up in our control.
mapinfo.Visible = true;
//Set the parent of MapInfo to a picture box on the form.
SetParent(oldhandle, this.pictureBox1.Handle);
//Get current window style of MapInfo window
int style = GetWindowLong(oldhandle, GWL_STYLE);
//Take current window style and remove WS_CAPTION(title bar) from it
SetWindowLong(oldhandle, GWL_STYLE, (style & ~WS_CAPTION));
//Maximize MapInfo so that it fits into our control.
mapinfo.Do("Set Window 1011 Max");
}
}
Class MapInfoApplication has a method called Do() and Eval(), there you can pass a command string, e.g. mapinfoinstance.Do('Open Table foo_bar.TAB as foo')
Have look at MapBasic samples in folder Samples\DOTNET\... in your MapBasic folder.
I'd like to display a little popup window next to the notification area. It's similar to what Outlook/Skype/Live! Messenger/etc does when it displays the notification about a new message. In my case it will have some input controls (textbox, datetimepicker, buttons...) so a simple bubble won't do.
The trick is doing this correctly when the user has multiple monitors and/or the taskbar is not located at the bottom of the screen. I could not find any functions that would let me determine the position and orientation of the taskbar/notification area.
Use WinAPI calls to find the TaskBar position, and position your window according to it
C# Example
class Program
{
static void Main(string[] args)
{
Taskbar taskbar = new Taskbar();
Console.WriteLine("Position: {0}, AlwaysOnTop: {1}; AutoHide: {2}; Bounds: {3}", taskbar.Position, taskbar.AlwaysOnTop, taskbar.AutoHide, taskbar.Bounds);
Console.ReadLine();
}
}
public enum TaskbarPosition
{
Unknown = -1,
Left,
Top,
Right,
Bottom,
}
public sealed class Taskbar
{
private const string ClassName = "Shell_TrayWnd";
public Rectangle Bounds
{
get;
private set;
}
public TaskbarPosition Position
{
get;
private set;
}
public Point Location
{
get
{
return this.Bounds.Location;
}
}
public Size Size
{
get
{
return this.Bounds.Size;
}
}
//Always returns false under Windows 7
public bool AlwaysOnTop
{
get;
private set;
}
public bool AutoHide
{
get;
private set;
}
public Taskbar()
{
IntPtr taskbarHandle = User32.FindWindow(Taskbar.ClassName, null);
APPBARDATA data = new APPBARDATA();
data.cbSize = (uint) Marshal.SizeOf(typeof(APPBARDATA));
data.hWnd = taskbarHandle;
IntPtr result = Shell32.SHAppBarMessage(ABM.GetTaskbarPos, ref data);
if (result == IntPtr.Zero)
throw new InvalidOperationException();
this.Position = (TaskbarPosition) data.uEdge;
this.Bounds = Rectangle.FromLTRB(data.rc.left, data.rc.top, data.rc.right, data.rc.bottom);
data.cbSize = (uint) Marshal.SizeOf(typeof(APPBARDATA));
result = Shell32.SHAppBarMessage(ABM.GetState, ref data);
int state = result.ToInt32();
this.AlwaysOnTop = (state & ABS.AlwaysOnTop) == ABS.AlwaysOnTop;
this.AutoHide = (state & ABS.Autohide) == ABS.Autohide;
}
}
public enum ABM : uint
{
New = 0x00000000,
Remove = 0x00000001,
QueryPos = 0x00000002,
SetPos = 0x00000003,
GetState = 0x00000004,
GetTaskbarPos = 0x00000005,
Activate = 0x00000006,
GetAutoHideBar = 0x00000007,
SetAutoHideBar = 0x00000008,
WindowPosChanged = 0x00000009,
SetState = 0x0000000A,
}
public enum ABE : uint
{
Left = 0,
Top = 1,
Right = 2,
Bottom = 3
}
public static class ABS
{
public const int Autohide = 0x0000001;
public const int AlwaysOnTop = 0x0000002;
}
public static class Shell32
{
[DllImport("shell32.dll", SetLastError = true)]
public static extern IntPtr SHAppBarMessage(ABM dwMessage, [In] ref APPBARDATA pData);
}
public static class User32
{
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}
[StructLayout(LayoutKind.Sequential)]
public struct APPBARDATA
{
public uint cbSize;
public IntPtr hWnd;
public uint uCallbackMessage;
public ABE uEdge;
public RECT rc;
public int lParam;
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
You need to get the actual location of your notification icon, and place your pop-up window near that (or wherever you like).
You need to translate your XY locations relative to desktop(s). AFAIK, there are no direct function, even in Win32 API which can directly give you the answer.
These sites will help you-
1. http://forum.codecall.net/managed-c/262-dual-monitors-window-position.html
2. http://msdn.microsoft.com/en-us/magazine/cc188759.aspx