我用C#寫了一個winform螢屏放大鏡工具,以滑鼠位置為中心,截取螢屏圖片,將圖游標圖片,實作實時放大。這個方法通過timer的tick事件不斷呼叫,我發現 Cursor = new Cursor(bitmap.GetHicon()); 這行代碼會不斷增加物理記憶體占用,導致系統逐漸變慢。請問各位大神有沒有什么解決辦法。
uj5u.com熱心網友回復:
你不斷的 Cursor = new Cursor(bitmap.GetHicon());那么在哪里釋放之前的 new Cursor(bitmap.GetHicon()) 的呢?
uj5u.com熱心網友回復:
new 就是創建物件 當然記憶體會增加uj5u.com熱心網友回復:
那應該怎么釋放呢?
uj5u.com熱心網友回復:
我就不明白做放大鏡怎么和 cursor 扯上關系了uj5u.com熱心網友回復:
附上相關代碼
private void RefreshImg()
{
var mousePos = MousePos;//滑鼠位置
var updatedBox = GetUpdatedBox(mousePos);//根據滑鼠位置繪制矩形
var img = GetDesktopImg(updatedBox);//獲取螢屏相關位置截圖
SetCursor(img);//將截圖轉換為游標
mousePos = new Point();
updatedBox = new Rectangle();
img = null;
}
private Rectangle GetUpdatedBox(Point p)
{
return Rectangle.Truncate(new RectangleF(p.X - magnifierWidth / zoomValue / 2, p.Y - magnifierHeight / zoomValue / 2, magnifierWidth / zoomValue, magnifierHeight / zoomValue));
}
private Bitmap GetDesktopImg(Rectangle rect)
{
IntPtr hWnd = GetDesktopWindow();
System.Drawing.Graphics grpScreen = System.Drawing.Graphics.FromHwnd(hWnd);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
System.Drawing.Graphics grpBitmap = System.Drawing.Graphics.FromImage(bitmap);
IntPtr hdcScreen = grpScreen.GetHdc();
IntPtr hdcBitmap = grpBitmap.GetHdc();
BitBlt(hdcBitmap, 0, 0, bitmap.Width, bitmap.Height, hdcScreen, rect.Left, rect.Top, 0x00CC0020);
grpBitmap.ReleaseHdc(hdcBitmap);
grpScreen.ReleaseHdc(hdcScreen);
grpBitmap.Dispose();
grpScreen.Dispose();
return bitmap;
}
private void SetCursor(Bitmap img)
{
using (var g = Graphics.FromImage(magnifierImg))
{
g.DrawImage(img, 0, 0, magnifierImg.Width, magnifierImg.Height);
g.DrawRectangle(new Pen(new SolidBrush(Color.Black)), new Rectangle(0, 0, magnifierImg.Width - 1, magnifierImg.Height - 1));
g.Dispose();
}
Cursor = new Cursor(magnifierImg.GetHicon());//如何釋放?
}
uj5u.com熱心網友回復:
把放大的影像做成滑鼠游標了
uj5u.com熱心網友回復:
一個放大鏡而已 哪有那么麻煩 而且壓根就沒有看到你的代碼里面哪里有放大圖片了
public partial class Form6 : Form
{
public Form6() {
InitializeComponent();
this.timer1.Interval = 50;
this.FormBorderStyle = FormBorderStyle.None;
}
private Point m_ptLast;
private Size m_szSrc;
private float m_fScale;
private Bitmap m_bmpSrc;
private void Form6_Load(object sender, EventArgs e) {
m_fScale = 4;
m_szSrc = new System.Drawing.Size(15, 15);
m_bmpSrc = new Bitmap(m_szSrc.Width, m_szSrc.Height);
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e) {
this.TopMost = true;//難道我系統出問題了?TopMost屬性居然無效了 只能放Timer里面不停的呼叫才有效 日了狗
if (m_ptLast == MousePosition) return;
m_ptLast = MousePosition;
using (Graphics g = Graphics.FromImage(m_bmpSrc)) {
g.CopyFromScreen(MousePosition.X - m_bmpSrc.Width / 2, MousePosition.Y - m_bmpSrc.Height / 2, 0, 0, m_bmpSrc.Size);
g.DrawRectangle(Pens.Magenta, 0, 0, m_bmpSrc.Width - 1, m_bmpSrc.Height - 1);
this.BackgroundImage = ZoomImage(m_bmpSrc, m_fScale);
this.Size = this.BackgroundImage.Size;
this.Left = MousePosition.X + 20;//根據滑鼠設定表單位置
this.Top = MousePosition.Y + 20; //這里沒有判斷表單是否超出螢屏邊緣
}
}
public static Image ZoomImage(Image image, float scale) {
if (image == null)
throw new ArgumentNullException("image cannot be null");
if (scale <= 0)
throw new ArgumentException("scale must be more than zero");
Bitmap bmp = new Bitmap((int)Math.Ceiling(image.Width * scale), (int)Math.Ceiling(image.Height * scale));
Bitmap bmpOld = image.Clone() as Bitmap;
BitmapData bmpDataNew = bmp.LockBits(new Rectangle(Point.Empty, bmp.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
BitmapData bmpDataOld = bmpOld.LockBits(new Rectangle(Point.Empty, image.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] byColorNew = new byte[bmpDataNew.Height * bmpDataNew.Stride];
byte[] byColorOld = new byte[bmpDataOld.Height * bmpDataOld.Stride];
Marshal.Copy(bmpDataOld.Scan0, byColorOld, 0, byColorOld.Length);
for (int x = 0, lenX = bmpDataNew.Width; x < lenX; x++) {
int srcX = (int)(x / scale) << 2;
for (int y = 0, lenY = bmpDataNew.Height; y < lenY; y++) {
int offsetOld = (int)(y / scale) * bmpDataOld.Stride + srcX;
int offsetNew = y * bmpDataNew.Stride + (x << 2);
if (offsetOld < 0) offsetOld = 0;
else if (offsetOld >= byColorOld.Length) offsetOld = byColorOld.Length - 1;
if (offsetNew < 0) offsetNew = 0;
else if (offsetNew >= byColorNew.Length) offsetNew = byColorNew.Length - 1;
byColorNew[offsetNew] = byColorOld[offsetOld];
byColorNew[offsetNew + 1] = byColorOld[offsetOld + 1];
byColorNew[offsetNew + 2] = byColorOld[offsetOld + 2];
byColorNew[offsetNew + 3] = byColorOld[offsetOld + 3];
}
}
bmpOld.UnlockBits(bmpDataOld);
Marshal.Copy(byColorNew, 0, bmpDataNew.Scan0, byColorNew.Length);
bmp.UnlockBits(bmpDataNew);
bmpOld.Dispose();
return bmp;
}
}
uj5u.com熱心網友回復:
這么寫小范圍縮放是挺好的,但是我想放大較大范圍的螢屏區域,這樣放大的區域和顯示區域重疊,好像會有問題
uj5u.com熱心網友回復:
在GetHicon之后使用DestroyIcon,[DllImport("user32.dll", CharSet = CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);
uj5u.com熱心網友回復:
using不行就去看看原始碼,應該自動釋放
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/82401.html
標籤:C#
上一篇:程式系統
