दिलचस्प पोस्ट
RKLog.h में 'Restkit' lcl_RK.h फ़ाइल को अपडेट नहीं किया गया WPF में स्वतः पूर्ण पाठ बॉक्स जावास्क्रिप्ट 'बाइंड' विधि का उपयोग करें आईडी का अर्थ क्या है? चार ए स्ट्रिंग के बीच अंतर क्या है ?; और चार * p =? स्ट्रिंग?;? जावा सर्वलेट में बड़ी फ़ाइलों को स्ट्रीम करना 2038 से परे PHP में तिथियां एक्सेस करना एक जेफ्राम और उसके घटकों को छपाई क्यों @ फ़ॉन्ट चेहरा woff फ़ाइलों पर एक 404 त्रुटि फेंक रहे हैं? सी # दशमांश शाब्दिक संकेतन में एम के लिए क्या खड़ा है? node.js को एक फ़ोल्डर में सभी फाइलों की आवश्यकता है? क्यों JsonRequestBehavior की आवश्यकता है? ASP.NET MVC – देखें या नियंत्रक में वर्तमान क्षेत्र का नाम प्राप्त करें बीन वैधीकरण @नोट नोबल, @ नॉटबैंक और @ नो एप्लीज जेएसएफ + टोमकेट में काम नहीं करता मैं एएसपी.नेट एमवीसी में लोअरकेस मार्ग कैसे कर सकता हूं?

सी # – माउस कर्सर छवि कैप्चरिंग

पृष्ठभूमि

  • मैं एक स्क्रीन कैप्चर आवेदन लिख रहा हूं
  • मेरा कोड इस परियोजना से प्राप्त होता है: http://www.codeproject.com/KB/cs/DesktopCaptureWithMouse.aspx?display=Print
  • ध्यान दें कि कोड माउस कर्सर को भी कैप्चर करता है (जो मेरे लिए वांछनीय है)

मेरी समस्या

  • जब माउस कर्सर सामान्य पॉइंटर या हाथ आइकन होता है तो कोड ठीक काम करता है – माउस को स्क्रीनशॉट पर सही ढंग से प्रस्तुत किया गया है
  • हालांकि, जब माउस कर्सर को सम्मिलन बिंदु ("आई-बीम" कर्सर) में बदल दिया जाता है – उदाहरण के लिए नोटपैड टाइपिंग – फिर कोड काम नहीं करता – परिणाम यह है कि मुझे कर्सर की बेहोश छवि मिलती है – जैसे कि रिक्त और सफेद के बजाय इसके बहुत ही पारदर्शी (ग्रे) संस्करण की उम्मीद होगी।

मेरा प्रश्न

  • जब छवि इन "आई-बीम" प्रकार की छवियों में से एक है, तो मैं माउस कर्सर छवि कैसे कैप्चर कर सकता हूं?
  • नोट: यदि आप मूल लेख पर क्लिक करते हैं तो कोई सुझाव प्रदान करता है – यह काम नहीं करता है

स्रोत

यह मूल लेख से है

static Bitmap CaptureCursor(ref int x, ref int y) { Bitmap bmp; IntPtr hicon; Win32Stuff.CURSORINFO ci = new Win32Stuff.CURSORINFO(); Win32Stuff.ICONINFO icInfo; ci.cbSize = Marshal.SizeOf(ci); if (Win32Stuff.GetCursorInfo(out ci)) { if (ci.flags == Win32Stuff.CURSOR_SHOWING) { hicon = Win32Stuff.CopyIcon(ci.hCursor); if (Win32Stuff.GetIconInfo(hicon, out icInfo)) { x = ci.ptScreenPos.x - ((int)icInfo.xHotspot); y = ci.ptScreenPos.y - ((int)icInfo.yHotspot); Icon ic = Icon.FromHandle(hicon); bmp = ic.ToBitmap(); return bmp; } } } return null; } 

वेब के समाधान से एकत्रित समाधान "सी # – माउस कर्सर छवि कैप्चरिंग"

हालांकि मैं वास्तव में ऐसा क्यों नहीं समझा सकता है, मुझे लगता है कि मैं इसके चारों ओर कैसे निकलना है यह दिखा सकता हूं।

ICONINFO स्ट्रक्चर में दो सदस्य, एचबीएम मास्क और एचबीएम कॉइलर होते हैं, जिनमें क्रमशः कर्सर के लिए मुखौटा और रंग बिटमैप होते हैं (आधिकारिक दस्तावेजों के लिए आईसीओएनआईएनओएफओ के लिए एमएसडीएन पृष्ठ देखें)।

जब आप डिफ़ॉल्ट कर्सर के लिए GetIconInfo () कहते हैं, तो ICONINFO स्ट्रैट में दोनों वैध मुखौटा और रंग बिटमैप शामिल हैं, जैसा कि नीचे दिखाया गया है (नोट: छवि सीमाओं को स्पष्ट रूप से दिखाने के लिए लाल सीमा जोड़ा गया है):

डिफ़ॉल्ट कर्सर मुखौटा बिटमैप डिफ़ॉल्ट कर्सर मास्क बिटमैप छवि http://img4.imageshack.us/img4/1108/arrowmask.png

डिफ़ॉल्ट कर्सर रंग बिटमैप डिफ़ॉल्ट कर्सर रंग बिटमैप छवि http://img191.imageshack.us/img191/7680/arrowcolor.png

जब Windows डिफ़ॉल्ट कर्सर को खींचता है, तो मुखौटा बिटमैप को पहले और रास्टर ऑपरेशन के साथ लागू किया जाता है, फिर रंग बिटमैप को एक्सओआर रास्टर ऑपरेशन के साथ लागू किया जाता है। यह एक अपारदर्शी कर्सर और एक पारदर्शी पृष्ठभूमि का परिणाम है।

I-बीम कर्सर के लिए GetIconInfo () को कॉल करते समय, हालांकि, ICONINFO स्ट्रक्चर में केवल एक वैध मुखौटा बिटमैप और कोई रंग बिटमैप नहीं है, जैसा कि नीचे दिखाया गया है (नोट: फिर से, लाल सीमा को छवि सीमाओं को स्पष्ट रूप से दिखाने के लिए जोड़ा गया है ):

आई-बीम कर्सर मास्क बिटमैप इबीम कर्सर मुखौटा बिटमैप छवि http://img14.imageshack.us/img14/6025/beammask.png

ICONINFO दस्तावेज़ीकरण के अनुसार, आई-बीम कर्सर तब एक मोनोक्रोम कर्सर है। मुखौटा बिटमैप का शीर्ष आधा और मुखौटा है, और मुखौटा बिटमैप का निचला अर्द्ध XOR बिटमैप है जब I-Beam कर्सर विंडोज खींचता है, तो इस बिटमैप का सबसे ऊपर आधा डेस्कटॉप पर एक एंड रास्टर ऑपरेशन के साथ खींचा जाता है। बिटमैप के निचले आधे हिस्से को एक्सओआर रास्टर ऑपरेशन के साथ शीर्ष पर खींचा जाता है। ऑनस्क्रीन, कर्सर इसके पीछे की सामग्री के व्युत्क्रम के रूप में दिखाई देगा।

आपके द्वारा लिंक किए गए मूल आलेख के लिए टिप्पणी में से एक यह बताता है। डेस्कटॉप पर, डेस्कटॉप सामग्री पर रेखापुंज संचालन लागू होने के बाद, कर्सर सही दिखाई देगा। हालांकि, जब छवि को कोई पृष्ठभूमि पर नहीं खींचा जाता है, जैसा कि आपके पोस्ट कोड में है, जो रेखापुंज संचालन करता है जो विंडोज एक फीका छवि में परिणाम करता है।

कहा जा रहा है कि, इस अद्यतन कैप्चरकर्सर () विधि रंग और मोनोक्रोम कर्सर दोनों को संभाल लेंगे, एक सादे काले कर्सर की छवि प्रदान करते समय कर्सर मोनोक्रोम होता है।

 static Bitmap CaptureCursor(ref int x, ref int y) { Win32Stuff.CURSORINFO cursorInfo = new Win32Stuff.CURSORINFO(); cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); if (!Win32Stuff.GetCursorInfo(out cursorInfo)) return null; if (cursorInfo.flags != Win32Stuff.CURSOR_SHOWING) return null; IntPtr hicon = Win32Stuff.CopyIcon(cursorInfo.hCursor); if (hicon == IntPtr.Zero) return null; Win32Stuff.ICONINFO iconInfo; if (!Win32Stuff.GetIconInfo(hicon, out iconInfo)) return null; x = cursorInfo.ptScreenPos.x - ((int)iconInfo.xHotspot); y = cursorInfo.ptScreenPos.y - ((int)iconInfo.yHotspot); using (Bitmap maskBitmap = Bitmap.FromHbitmap(iconInfo.hbmMask)) { // Is this a monochrome cursor? if (maskBitmap.Height == maskBitmap.Width * 2) { Bitmap resultBitmap = new Bitmap(maskBitmap.Width, maskBitmap.Width); Graphics desktopGraphics = Graphics.FromHwnd(Win32Stuff.GetDesktopWindow()); IntPtr desktopHdc = desktopGraphics.GetHdc(); IntPtr maskHdc = Win32Stuff.CreateCompatibleDC(desktopHdc); IntPtr oldPtr = Win32Stuff.SelectObject(maskHdc, maskBitmap.GetHbitmap()); using (Graphics resultGraphics = Graphics.FromImage(resultBitmap)) { IntPtr resultHdc = resultGraphics.GetHdc(); // These two operation will result in a black cursor over a white background. // Later in the code, a call to MakeTransparent() will get rid of the white background. Win32Stuff.BitBlt(resultHdc, 0, 0, 32, 32, maskHdc, 0, 32, Win32Stuff.TernaryRasterOperations.SRCCOPY); Win32Stuff.BitBlt(resultHdc, 0, 0, 32, 32, maskHdc, 0, 0, Win32Stuff.TernaryRasterOperations.SRCINVERT); resultGraphics.ReleaseHdc(resultHdc); } IntPtr newPtr = Win32Stuff.SelectObject(maskHdc, oldPtr); Win32Stuff.DeleteObject(newPtr); Win32Stuff.DeleteDC(maskHdc); desktopGraphics.ReleaseHdc(desktopHdc); // Remove the white background from the BitBlt calls, // resulting in a black cursor over a transparent background. resultBitmap.MakeTransparent(Color.White); return resultBitmap; } } Icon icon = Icon.FromHandle(hicon); return icon.ToBitmap(); } 

ऐसे कोड के साथ कुछ समस्याएं हैं जो एक समस्या हो सकती हैं या नहीं।

  1. एक मोनोक्रोम कर्सर की जांच केवल जांच करती है कि ऊंचाई चौड़ाई से दो बार है। हालांकि यह तर्कसंगत लगता है, ICONINFO दस्तावेज़ों का यह जिक्र नहीं है कि केवल एक मोनोक्रोम कर्सर को इस द्वारा परिभाषित किया गया है।
  2. शायद कर्सर को प्रस्तुत करने का एक बेहतर तरीका हो सकता है कि बिटब्लैट () – बिटब्लैट () – मेकट्रानपेरेंट () विधि कॉल का संयोजन जिसे मैंने इस्तेमाल किया था
 [StructLayout(LayoutKind.Sequential)] struct CURSORINFO { public Int32 cbSize; public Int32 flags; public IntPtr hCursor; public POINTAPI ptScreenPos; } [StructLayout(LayoutKind.Sequential)] struct POINTAPI { public int x; public int y; } [DllImport("user32.dll")] static extern bool GetCursorInfo(out CURSORINFO pci); [DllImport("user32.dll")] static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon); const Int32 CURSOR_SHOWING = 0x00000001; public static Bitmap CaptureScreen(bool CaptureMouse) { Bitmap result = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format24bppRgb); try { using (Graphics g = Graphics.FromImage(result)) { g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy); if (CaptureMouse) { CURSORINFO pci; pci.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(CURSORINFO)); if (GetCursorInfo(out pci)) { if (pci.flags == CURSOR_SHOWING) { DrawIcon(g.GetHdc(), pci.ptScreenPos.x, pci.ptScreenPos.y, pci.hCursor); g.ReleaseHdc(); } } } } } catch { result = null; } return result; } 

यहां दीमीटर की प्रतिक्रिया का एक संशोधित संस्करण है (ड्राआईकॉनएक्स द्वारा) जो कि मेरे लिए एकाधिक स्क्रीन पर काम करता है:

 public class ScreenCapturePInvoke { [StructLayout(LayoutKind.Sequential)] private struct CURSORINFO { public Int32 cbSize; public Int32 flags; public IntPtr hCursor; public POINTAPI ptScreenPos; } [StructLayout(LayoutKind.Sequential)] private struct POINTAPI { public int x; public int y; } [DllImport("user32.dll")] private static extern bool GetCursorInfo(out CURSORINFO pci); [DllImport("user32.dll", SetLastError = true)] static extern bool DrawIconEx(IntPtr hdc, int xLeft, int yTop, IntPtr hIcon, int cxWidth, int cyHeight, int istepIfAniCur, IntPtr hbrFlickerFreeDraw, int diFlags); private const Int32 CURSOR_SHOWING = 0x0001; private const Int32 DI_NORMAL = 0x0003; public static Bitmap CaptureFullScreen(bool captureMouse) { var allBounds = Screen.AllScreens.Select(s => s.Bounds).ToArray(); Rectangle bounds = Rectangle.FromLTRB(allBounds.Min(b => b.Left), allBounds.Min(b => b.Top), allBounds.Max(b => b.Right), allBounds.Max(b => b.Bottom)); var bitmap = CaptureScreen(bounds, captureMouse); return bitmap; } public static Bitmap CapturePrimaryScreen(bool captureMouse) { Rectangle bounds = Screen.PrimaryScreen.Bounds; var bitmap = CaptureScreen(bounds, captureMouse); return bitmap; } public static Bitmap CaptureScreen(Rectangle bounds, bool captureMouse) { Bitmap result = new Bitmap(bounds.Width, bounds.Height); try { using (Graphics g = Graphics.FromImage(result)) { g.CopyFromScreen(bounds.Location, Point.Empty, bounds.Size); if (captureMouse) { CURSORINFO pci; pci.cbSize = Marshal.SizeOf(typeof (CURSORINFO)); if (GetCursorInfo(out pci)) { if (pci.flags == CURSOR_SHOWING) { var hdc = g.GetHdc(); DrawIconEx(hdc, pci.ptScreenPos.x-bounds.X, pci.ptScreenPos.y-bounds.Y, pci.hCursor, 0, 0, 0, IntPtr.Zero, DI_NORMAL); g.ReleaseHdc(); } } } } } catch { result = null; } return result; } } 

I-बीम कर्सर के एक पारभासी 'ग्रे' संस्करण का आपका वर्णन मुझे आश्चर्य करता है कि क्या आप छवि स्केलिंग या कर्सर की गलत वर्तनी के साथ किसी समस्या का सामना कर रहे हैं।

उस साइट पर पोस्ट करने वाले लोगों में से एक ने अजीब व्यवहार के साथ एक रिपोर्ट को (टूटी हुई) लिंक प्रदान किया है जिस पर मैंने नीचे ट्रैक किया है: http://www.efg2.com/Lab/Graphics/CursorOverlay.htm

उस पृष्ठ के उदाहरण C # पर नहीं हैं, लेकिन codeproject समाधान के लेखक कुछ इसी तरह कर रहे हैं और मुझे पता है कि मेरे पास बहुत सारे अवसरों पर ग्राफिक्स ऑब्जेक्ट का उपयोग करते समय मैंने अपने स्केलिंग को खराब कर दिया है:

एक छवि लोड हो जाने के बाद किसी भी इमेजमेउसडाउन ईवेंट में, क्यूसरबिटमैप को कैनवास.ड्राऊथ विधि का उपयोग करके बिटमैप के ऊपर पारदर्शिता से तैयार किया गया है। ध्यान दें कि कुछ समन्वय समायोजन (rescaling) की आवश्यकता होती है, यदि बिटमैप को TImage में फिट करने के लिए बढ़ाया गया है।

यह इस पृष्ठ पर प्रस्तुत की गई बगों के लिए सभी फ़िक्स के साथ पैच संस्करण है:

 public static Bitmap CaptureImageCursor(ref Point point) { try { var cursorInfo = new CursorInfo(); cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); if (!GetCursorInfo(out cursorInfo)) return null; if (cursorInfo.flags != CursorShowing) return null; var hicon = CopyIcon(cursorInfo.hCursor); if (hicon == IntPtr.Zero) return null; Iconinfo iconInfo; if (!GetIconInfo(hicon, out iconInfo)) { DestroyIcon(hicon); return null; } point.X = cursorInfo.ptScreenPos.X - iconInfo.xHotspot; point.Y = cursorInfo.ptScreenPos.Y - iconInfo.yHotspot; using (var maskBitmap = Image.FromHbitmap(iconInfo.hbmMask)) { //Is this a monochrome cursor? if (maskBitmap.Height == maskBitmap.Width * 2 && iconInfo.hbmColor == IntPtr.Zero) { var final = new Bitmap(maskBitmap.Width, maskBitmap.Width); var hDesktop = GetDesktopWindow(); var dcDesktop = GetWindowDC(hDesktop); using (var resultGraphics = Graphics.FromImage(final)) { var resultHdc = resultGraphics.GetHdc(); BitBlt(resultHdc, 0, 0, final.Width, final.Height, dcDesktop, (int)point.X + 3, (int)point.Y + 3, CopyPixelOperation.SourceCopy); DrawIconEx(resultHdc, 0, 0, cursorInfo.hCursor, 0, 0, 0, IntPtr.Zero, 0x0003); //TODO: I have to try removing the background of this cursor capture. //Native.BitBlt(resultHdc, 0, 0, final.Width, final.Height, dcDesktop, (int)point.X + 3, (int)point.Y + 3, Native.CopyPixelOperation.SourceErase); resultGraphics.ReleaseHdc(resultHdc); ReleaseDC(hDesktop, dcDesktop); } DeleteObject(iconInfo.hbmMask); DeleteDC(dcDesktop); DestroyIcon(hicon); return final; } DeleteObject(iconInfo.hbmColor); DeleteObject(iconInfo.hbmMask); DestroyIcon(hicon); } var icon = Icon.FromHandle(hicon); return icon.ToBitmap(); } catch (Exception ex) { //You should catch exception with your method here. //LogWriter.Log(ex, "Impossible to get the cursor."); } return null; } 

इस संस्करण के साथ काम करता है:

  1. आई-बीम कर्सर
  2. काली कर्सर
  3. सामान्य कर्सर
  4. उल्टे कर्सर

यहां देखें, काम करें: https://github.com/NickeManarin/ScreenToGif/blob/master/ScreenToGif/Util/Native.cs#L991

अन्य उत्तरों के आधार पर मैंने सभी विंडोज़ एपीआई सामान (मोनोक्रोम भाग के लिए) के बिना एक संस्करण बनाया क्योंकि समाधान सभी मोनोक्रोम कर्सर के लिए काम नहीं करते थे। मैं दो मुखौटा भागों के संयोजन से मुखौटा से कर्सर बना रहा हूँ।

मेरा समाधान:

 Bitmap CaptureCursor(ref Point position) { CURSORINFO cursorInfo = new CURSORINFO(); cursorInfo.cbSize = Marshal.SizeOf(cursorInfo); if (!GetCursorInfo(out cursorInfo)) return null; if (cursorInfo.flags != CURSOR_SHOWING) return null; IntPtr hicon = CopyIcon(cursorInfo.hCursor); if (hicon == IntPtr.Zero) return null; ICONINFO iconInfo; if (!GetIconInfo(hicon, out iconInfo)) return null; position.X = cursorInfo.ptScreenPos.x - iconInfo.xHotspot; position.Y = cursorInfo.ptScreenPos.y - iconInfo.yHotspot; using (Bitmap maskBitmap = Bitmap.FromHbitmap(iconInfo.hbmMask)) { // check for monochrome cursor if (maskBitmap.Height == maskBitmap.Width * 2) { Bitmap cursor = new Bitmap(32, 32, PixelFormat.Format32bppArgb); Color BLACK = Color.FromArgb(255, 0, 0, 0); //cannot compare Color.Black because of different names Color WHITE = Color.FromArgb(255, 255, 255, 255); //cannot compare Color.White because of different names for (int y = 0; y < 32; y++) { for (int x = 0; x < 32; x++) { Color maskPixel = maskBitmap.GetPixel(x, y); Color cursorPixel = maskBitmap.GetPixel(x, y + 32); if (maskPixel == WHITE && cursorPixel == BLACK) { cursor.SetPixel(x, y, Color.Transparent); } else if (maskPixel == BLACK) { cursor.SetPixel(x, y, cursorPixel); } else { cursor.SetPixel(x, y, cursorPixel == BLACK ? WHITE : BLACK); } } } return cursor; } } Icon icon = Icon.FromHandle(hicon); return icon.ToBitmap(); }