コード例 #1
0
        public static Rectangle GetWorkArea(this Screen screen, out double screenFactor, out double dpiFactor, out int barEdge)
        {
            RECT barRect = new RECT();
            var  bounds  = screen.GetBounds();

            string[] tbClassNames = new string[] { "Shell_TrayWnd", "Shell_SecondaryTrayWnd" };
            if (screen.Primary == false)
            {
                tbClassNames = new string[] { "Shell_SecondaryTrayWnd", "Shell_TrayWnd" };
            }
            IntPtr    taskbarHandle;
            Rectangle logicBounds;
            Rectangle bRect;

            screenFactor = 1;
            dpiFactor    = 1;
            barEdge      = 3;
            foreach (var className in tbClassNames)
            {
                taskbarHandle = FindWindowEx(IntPtr.Zero, IntPtr.Zero, className, null);
                GetWindowRect(taskbarHandle, out barRect);
                var          g  = Graphics.FromHwnd(taskbarHandle);
                var          h  = g.GetHdc();
                SafeDCHandle sh = new SafeDCHandle(taskbarHandle, h);
                int          LogicalScreenHeight  = Gdi32.GetDeviceCaps(sh, DeviceCap.VERTRES);
                int          PhysicalScreenHeight = Gdi32.GetDeviceCaps(sh, DeviceCap.DESKTOPVERTRES);
                int          logpixelsy           = Gdi32.GetDeviceCaps(sh, DeviceCap.LOGPIXELSY);
                screenFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
                dpiFactor    = (float)logpixelsy / (float)96;
                sh.Dispose();

                if (taskbarHandle == IntPtr.Zero)
                {
                    return(bounds);
                }
                //}
                //else
                //{
                //    var data = new APPBARDATA();
                //    data.cbSize = Marshal.SizeOf(data);
                //    var ret = SHAppBarMessage((int)ABMsg.ABM_GETTASKBARPOS, ref data);
                //    barRect = data.rc;
                //}
                bRect = Rectangle.FromLTRB(barRect.left, barRect.top, barRect.right, barRect.bottom);
                var bRect2 = Rectangle.FromLTRB(barRect.left, barRect.top, barRect.right, barRect.bottom);
                bRect2.Inflate(-5, -5);
                var dx = 1;
                var dy = 1;
                logicBounds = new Rectangle(bounds.X, bounds.Y, (int)(bounds.Width * dx), (int)(bounds.Height * dy));
                //var logicBounds = bounds;
                if (logicBounds.Contains(bRect2) == false)
                {
                    continue;
                }
                barEdge = 3;
                var l = bounds.Left;
                var t = bounds.Top;
                var r = bounds.Right;
                var b = bounds.Bottom;
                if (Math.Abs(logicBounds.Right - bRect.Right) > 5)
                {
                    barEdge = 0;
                    l       = (int)(bRect.Right / dx);
                }
                else if (Math.Abs(logicBounds.Bottom - bRect.Bottom) > 5)
                {
                    barEdge = 1;
                    t       = (int)(bRect.Bottom / dy);
                }
                else if (Math.Abs(logicBounds.Left - bRect.Left) > 5)
                {
                    barEdge = 2;
                    r       = (int)(bRect.Left / dx);
                }
                else if (Math.Abs(logicBounds.Top - bRect.Top) > 5)
                {
                    barEdge = 3;
                    b       = (int)(bRect.Top / dy);
                }
                var clientBounds = Rectangle.FromLTRB(l, t, r, b);
                return(clientBounds);
            }

            return(bounds);
        }
コード例 #2
0
        /// <summary>
        /// カーソルの画像を取得する
        /// </summary>
        /// <param name="iconHandle">
        /// カーソルアイコンへのハンドル
        /// </param>
        /// <param name="iconInfo">
        /// カーソルアイコン情報
        /// </param>
        /// <param name="backgroundImage">
        /// カーソルの背景画像(NULLを指定した場合は白一色の背景として描画する)
        /// </param>
        /// <param name="drawPoint">
        /// 背景画像に対してカーソルを描画する座標
        /// (背景画像を使用しない場合は NULL を指定する)</param>
        /// <exception cref="PlatformInvokeException">
        /// Win32Apiの下記の処理の呼び出しに失敗した場合に発生
        /// ・「DLL:gdi32.dll、メソッド:CreateCompatibleDC」
        /// ・「DLL:gdi32.dll、メソッド:SelectObject」
        /// ・「DLL:gdi32.dll、メソッド:BitBlt」
        /// ・「DLL:gdi32.dll、メソッド:DeleteObject」
        /// ・「DLL:gdi32.dll、メソッド:DeleteDC」
        /// </exception>
        /// <exception cref="Win32OperateException">
        /// Win32Apiの下記の処理に失敗した場合に発生
        /// ・「DLL:gdi32.dll、メソッド:CreateCompatibleDC」
        /// ・「DLL:gdi32.dll、メソッド:SelectObject」
        /// ・「DLL:gdi32.dll、メソッド:BitBlt」
        /// ・「DLL:gdi32.dll、メソッド:DeleteObject」
        /// ・「DLL:gdi32.dll、メソッド:DeleteDC」
        /// </exception>
        /// <returns>カーソル画像(取得できない場合はNULLを返却する)</returns>
        private static Bitmap GetCursorImage(
            SafeCopyIconHandle iconHandle,
            IconInfo.ICONINFO iconInfo,
            Bitmap backgroundImage = null,
            Point?drawPoint        = null)
        {
            // カラー・マスク情報が存在するか判定
            bool hasColor = IsBitmap(iconInfo.ColorBitmapHandle);
            bool hasMask  = IsBitmap(iconInfo.MaskBitmapHandle);

            // アイコンのカラー、マスクの両方が取得できない場合
            // 画像情報は取得できないため NULL を返す
            if (!hasColor && !hasMask)
            {
                return(null);
            }

            // アイコンのハンドルからカーソルアイコンを取得する
            Icon cursorIcon;

            try
            {
                cursorIcon = Icon.FromHandle(iconHandle.Handle);
            }
            catch (ExternalException)
            {
                // アイコンのハンドルからカーソルアイコンを生成できない場合、NULL を返す
                return(null);
            }

            // カーソルがモノクロかカラーでそれぞれ取得を行う
            if (hasColor)
            {
                // カラーの場合
                // アイコン画像をビットマップ形式に変換して、そのまま返す
                return(cursorIcon.ToBitmap());
            }

            // モノクロの場合

            // 画像に関するリソースの解放用の宣言
            Bitmap   cursorImage         = null;
            Graphics cursorImageGraphics = null;
            Bitmap   baseImage           = null;
            Bitmap   maskImage           = null;
            bool     isCreateBase        = false;

            try
            {
                // 各画像データの生成
                // カーソル画像と、グラフィックオブジェクト生成
                cursorImage         = new Bitmap(cursorIcon.Width, cursorIcon.Height);
                cursorImageGraphics = Graphics.FromImage(cursorImage);

                // 背景画像の生成
                // 引数で背景画像が与えられていない場合、白一色の背景画像を生成する
                if (backgroundImage == null)
                {
                    baseImage = new Bitmap(cursorIcon.Width, cursorIcon.Height);
                    using (Graphics graphics = Graphics.FromImage(baseImage))
                    {
                        graphics.FillRectangle(Brushes.White, graphics.VisibleClipBounds);
                    }

                    isCreateBase = true;
                }
                else
                {
                    isCreateBase = false;
                }

                // マスク画像の生成
                maskImage = Image.FromHbitmap(iconInfo.MaskBitmapHandle);

                // アンマネージリソースの解放用の宣言
                SafeDCHandle cursorHdc  = null;
                SafeDCHandle baseHdc    = null;
                SafeDCHandle maskHdc    = null;
                IntPtr       beforeBase = IntPtr.Zero;
                IntPtr       beforeMask = IntPtr.Zero;
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                    // カーソル画像のデバイスコンテキストを取得
                    cursorHdc = new SafeDCHandle(cursorImageGraphics);

                    // 背景画像のデバイスコンテキストを取得
                    IntPtr baseHBitmap = isCreateBase
                        ? baseImage.GetHbitmap() : backgroundImage.GetHbitmap();
                    baseHdc    = CreateCompatibleDC(IntPtr.Zero);
                    beforeBase = SelectBitmap(baseHdc, baseHBitmap);

                    // マスク画像のデバイスコンテキストを取得
                    IntPtr maskHBitmap = maskImage.GetHbitmap();
                    maskHdc    = CreateCompatibleDC(IntPtr.Zero);
                    beforeMask = SelectBitmap(maskHdc, maskHBitmap);

                    // 画像の合成処理
                    int   width   = cursorImage.Width;
                    int   height  = cursorImage.Height;
                    Point base1Pt = drawPoint ?? new Point(0, 0);
                    Point mask1Pt = new Point(0, 0);
                    Point mask2Pt = new Point(0, maskImage.Height / 2);
                    BitBlt(cursorHdc, 0, 0, width, height, baseHdc, base1Pt.X, base1Pt.Y, ROPCode.SRCCOPY);
                    BitBlt(cursorHdc, 0, 0, width, height, maskHdc, mask1Pt.X, mask1Pt.Y, ROPCode.SRCAND);
                    BitBlt(cursorHdc, 0, 0, width, height, maskHdc, mask2Pt.X, mask2Pt.Y, ROPCode.SRCINVERT);
                }
                finally
                {
                    // リソースの解放処理
                    // カーソル画像に関するリソースの解放
                    try
                    {
                    }
                    finally
                    {
                        cursorHdc.Dispose();
                    }

                    // 元となる背景画像に関するリソースの解放
                    try
                    {
                        if (baseHdc != null)
                        {
                            IntPtr baseHandle = SelectBitmap(baseHdc, beforeBase);

                            if (baseHandle != IntPtr.Zero)
                            {
                                DeleteObject(baseHandle);
                            }
                        }
                    }
                    finally
                    {
                        baseHdc?.Dispose();
                    }

                    // マスク画像に関するリソースの解放
                    try
                    {
                        if (maskHdc != null)
                        {
                            IntPtr maskHandle = SelectBitmap(maskHdc, beforeMask);

                            if (maskHandle != IntPtr.Zero)
                            {
                                DeleteObject(maskHandle);
                            }
                        }
                    }
                    finally
                    {
                        maskHdc?.Dispose();
                    }
                }
            }
            catch
            {
                // 例外発生時はカーソル画像を破棄する
                cursorImage.Dispose();

                // 発生した例外はそのままスローする
                throw;
            }
            finally
            {
                // 画像リソースを解放する
                cursorImageGraphics?.Dispose();
                baseImage?.Dispose();
                maskImage?.Dispose();
            }

            // 背景画像を白一色で生成した場合、背景を透過する
            if (isCreateBase)
            {
                cursorImage.MakeTransparent(Color.White);
            }

            // 合成したカーソル画像を返す
            return(cursorImage);
        }