winform圖片標尺控制項

来源:http://www.cnblogs.com/rocpeng/archive/2017/12/05/7988683.html
-Advertisement-
Play Games

最近要做個winform的東西,要在裡面集成一個類似Windows自帶畫圖的標尺功能,還要能在圖片上畫矩形框。在網上找了好久也沒找到寫好的控制項,無奈自己做了一個。 目前還有些bug,這裡先做個分享。(Ps:很少做winform的東西,做的不好,輕噴。另外歡迎指點。) 由於最後要做的東西的背景是黑的, ...


最近要做個winform的東西,要在裡面集成一個類似Windows自帶畫圖的標尺功能,還要能在圖片上畫矩形框。在網上找了好久也沒找到寫好的控制項,無奈自己做了一個。

目前還有些bug,這裡先做個分享。(Ps:很少做winform的東西,做的不好,輕噴。另外歡迎指點。)

由於最後要做的東西的背景是黑的,標尺就畫成白的了,有需要的自己改吧。。

直接上代碼

 

  1 using Helper;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Drawing;
  5 using System.Windows.Forms;
  6 
  7 namespace UserCtrl
  8 {
  9     public partial class RulerControl : UserControl
 10     {
 11         private double _monitorDPI = 100;
 12         /// <summary>
 13         /// 用於控制放大倍數
 14         /// </summary>
 15         private double _multiple = 1;
 16 
 17         /// <summary>
 18         /// 每多少個像素1格
 19         /// </summary>
 20         public double MonitorDPI
 21         {
 22             get
 23             {
 24                 return _monitorDPI;
 25             }
 26             set
 27             {
 28                 _monitorDPI = value;
 29             }
 30         }    
 31         /// <summary>
 32         /// X軸偏移位置
 33         /// </summary>
 34         private float offSetX=0;
 35 
 36         /// <summary>
 37         /// Y軸偏移位置
 38         /// </summary>
 39         private float offSetY = 0;
 40 
 41         /// <summary>
 42         /// 開始位置X
 43         /// </summary>
 44         public double XStart
 45         {
 46             get;
 47             set;
 48         }
 49 
 50         /// <summary>
 51         /// 開始位置Y
 52         /// </summary>
 53         public double YStart
 54         {
 55             get;
 56             set;
 57         }
 58 
 59         /// <summary>
 60         /// 用戶設置的原始圖
 61         /// </summary>
 62         private Image _initImg = null;
 63 
 64 
 65 
 66         /// <summary>
 67         /// 圖片
 68         /// </summary>
 69         public Image Image
 70         {
 71             get
 72             {
 73                 return Pic.Image;
 74             }
 75             set
 76             {
 77                 Pic.Image = value;
 78                 if (_initImg == null&&value!=null)
 79                 {
 80                     _initImg = PicHelper.GetNewPic(value, value.Width , value.Height );
 81                 }
 82             }
 83         }
 84         private Font font = new Font("宋體", 9); //刻度值顯示字體
 85         public RulerControl()
 86         {
 87             InitializeComponent();
 88         }
 89 
 90         private void Pic_MouseWheel(object sender, MouseEventArgs e)
 91         {
 92             if (MouseButtons == MouseButtons.Left)
 93             {
 94                 return;
 95             }
 96             Image img = Pic.Image;
 97             if (img != null)
 98             {
 99                 if (e.Delta >= 0)
100                 {
101                     if (_multiple * 2 > 4)
102                         return;
103                     _multiple *= 2;
104                 }
105                 else
106                 {
107                     if (Pic.Width < this.Width - 50)
108                         return;
109 
110                     _multiple *= 0.5;
111                     if (Pic.Width <= (this.Width - 50))
112                     {
113                         XStart = 0;
114                         YStart = 0;
115                     }
116                 }
117                 DrawRect();
118                 AdapterDpi();
119                 ReDrawX();
120                 ReDrawY();
121             }
122         }
123 
124         private void RulerControl_Paint(object sender, PaintEventArgs e)
125         {
126             P1.Height = 50;
127             P1.Width = this.Width - 50;
128             P2.Height = this.Height - 50;
129             P2.Width = 50;
130             P1.Location = new Point(50, 0);
131             P2.Location = new Point(0, 50);
132             PContainer.Location = new Point(50, 50);
133         }
134 
135         private void RulerControl_Resize(object sender, EventArgs e)
136         {
137             P1.Height = 50;
138             P1.Width = this.Width - 50;
139             P2.Height = this.Height - 50;
140             P2.Width = 50;
141             P1.Location = new Point(50, 0);
142             P2.Location = new Point(0, 50);
143             PContainer.Location = new Point(50, 50);
144         }
145 
146         /// <summary>
147         /// 重畫Y軸
148         /// </summary>
149         private void ReDrawY()
150         {
151             if (P2.BackgroundImage != null)
152             {
153                 P2.BackgroundImage.Dispose();
154             }
155             Bitmap bmpY = new Bitmap(P2.Width, P2.Height);
156             using (Graphics g = Graphics.FromImage(bmpY))
157             {
158                 int originLocation = bmpY.Width - 1;
159                 int startY = (int)Math.Ceiling(YStart);
160                 offSetY = (float)(MonitorDPI * _multiple * (startY - YStart));
161                 for (int i = startY; i <= Math.Ceiling(P2.Height / (MonitorDPI * _multiple) + YStart); i++)
162                 {
163                     float y = (float)(MonitorDPI * _multiple * (i - YStart)) + offSetY;
164                     if (y >= 0)
165                     {
166                         PointF start = new PointF(originLocation, y);
167                         PointF end = new PointF(originLocation - 3, y);
168                         if (i % 5 == 0)
169                         {
170                             end = new PointF(originLocation - 6, y);
171                         }
172                         if (i % 10 == 0 && i != 0)
173                         {
174                             end = new PointF(originLocation - 12, y);
175                             g.DrawString((i*MonitorDPI).ToString(), font, Brushes.White, new PointF(originLocation - 30, y - 5));
176                         }
177                         g.DrawLine(Pens.White, start, end);
178                     }
179                 }
180                 g.DrawLine(Pens.White, new PointF(originLocation, 0), new PointF(originLocation, bmpY.Height));
181                 P2.BackgroundImage = bmpY;
182             }
183         }
184 
185         /// <summary>
186         /// 重畫X軸
187         /// </summary>
188         private void ReDrawX()
189         {
190             if (P1.BackgroundImage != null)
191             {
192                 P1.BackgroundImage.Dispose();
193             }
194             Bitmap bmpX = new Bitmap(P1.Width, P1.Height);
195             using (Graphics g = Graphics.FromImage(bmpX))
196             {
197                 int originLocation = bmpX.Height - 1;
198                 int startX = (int)Math.Ceiling(XStart);
199                 offSetX = (float)(MonitorDPI * _multiple * (startX - XStart));
200                 for (int i = startX; i <= Math.Ceiling(P1.Width / (MonitorDPI * _multiple) + XStart); i++)
201                 {
202                     float x = (float)(MonitorDPI * _multiple * (i - XStart)) + offSetX;
203                     if (x >= 0)
204                     {
205                         PointF start = new PointF(x, originLocation);
206                         PointF end = new PointF(x, originLocation - 3);
207                         if (i % 5 == 0)
208                         {
209                             end = new PointF(x, originLocation - 6);
210                         }
211                         if (i % 10 == 0 && i != 0)
212                         {
213                             end = new PointF(x, originLocation - 12);
214                             g.DrawString((i*MonitorDPI).ToString(), font, Brushes.White, new PointF(x - 5, originLocation - 30));
215                         }
216                         g.DrawLine(Pens.White, start, end);
217                     }
218                 }
219                 g.DrawLine(Pens.White, new PointF(0, originLocation), new PointF(bmpX.Width, originLocation));
220                 P1.BackgroundImage = bmpX;
221             }
222         }
223 
224         private void RulerControl_Load(object sender, EventArgs e)
225         {
226             P1.Height = 50;
227             P1.Width = this.Width - 50;
228             P2.Height = this.Height - 50;
229             P2.Width = 50;
230             P1.Location = new Point(50, 0);
231             P2.Location = new Point(0, 50);
232             PContainer.Location = new Point(50, 50);
233             ReDrawX();
234             ReDrawY();
235             Pic.MouseWheel += new MouseEventHandler(Pic_MouseWheel);
236         }
237 
238         private void Pic_MouseEnter(object sender, EventArgs e)
239         {
240             Pic.Focus();
241         }
242 
243         private void PContainer_Scroll(object sender, ScrollEventArgs e)
244         {
245             if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
246             {
247                 XStart = e.NewValue / (MonitorDPI * _multiple);
248                 ReDrawX();
249             }
250             else if (e.ScrollOrientation == ScrollOrientation.VerticalScroll)
251             {
252                 YStart = e.NewValue / (MonitorDPI * _multiple);
253                 ReDrawY();
254             }
255         }
256 
257 
258         #region 畫圖片選定區域
259         bool MouseIsDown = false;
260         Rectangle MouseRect = Rectangle.Empty;
261 
262         private void Pic_MouseDown(object sender, MouseEventArgs e)
263         {
264             MouseIsDown = true;
265             MouseRect = new Rectangle(e.X, e.Y, 0, 0);
266             Rectangle rec = new Rectangle(0, 0,
267                 Math.Min(PContainer.ClientRectangle.Width, Pic.ClientRectangle.Width),
268                 Math.Min(PContainer.ClientRectangle.Height, Pic.ClientRectangle.Height));
269             Cursor.Clip = PContainer.RectangleToScreen(rec);
270         }
271 
272         private void Pic_MouseMove(object sender, MouseEventArgs e)
273         {
274             if (MouseIsDown)
275             {
276                 MouseRect.Width = e.X - MouseRect.Left;
277                 MouseRect.Height = e.Y - MouseRect.Top;
278                 if (MouseRect.Width > 0 && MouseRect.Height > 0)
279                 {
280                     Rectangle rect = Pic.RectangleToScreen(MouseRect);
281                     ControlPaint.DrawReversibleFrame(rect, Color.White, FrameStyle.Dashed);
282                 }
283                 Pic.Refresh();
284             }
285 
286         }
287 
288         private void Pic_MouseUp(object sender, MouseEventArgs e)
289         {
290             if (MouseIsDown)
291             {
292                 MouseRect.Width = e.X - MouseRect.Left;
293                 MouseRect.Height = e.Y - MouseRect.Top;
294                 using (Graphics g = Graphics.FromImage(Pic.Image))
295                 {
296                     g.DrawRectangle(new Pen(Color.Red), MouseRect);
297                 }
298                 Pic.Refresh();
299                 MouseIsDown = false;
300                 if ((int)(MouseRect.Width * _multiple) > 0 && (int)(MouseRect.Height * _multiple) > 0)
301                 {
302                     list.Add(new Rectangle((int)(MouseRect.X / _multiple),
303                         (int)(MouseRect.Y / _multiple),
304                         (int)(MouseRect.Width / _multiple),
305                         (int)(MouseRect.Height / _multiple)
306                         ));
307                 }
308                 MouseRect = Rectangle.Empty;
309                 Cursor.Clip = Rectangle.Empty;
310             }
311         }
312         #endregion
313         public List<Rectangle> list = new List<Rectangle>();
314 
315         private void Pic_DoubleClick(object sender, EventArgs e)
316         {
317             MouseEventArgs ev = e as MouseEventArgs;
318             List<Rectangle> temp = new List<Rectangle>();
319             foreach (Rectangle item in list)
320             {
321                 if (ev.X > item.X * _multiple && ev.X < item.X * _multiple + item.Width * _multiple &&
322                     ev.Y > item.Y * _multiple && ev.Y < item.Y * _multiple + item.Height * _multiple)
323                 {
324                     temp.Add(item);
325                 }
326             }
327             foreach (Rectangle item in temp)
328             {
329                 list.Remove(item);
330             }
331             
332             DrawRect();
333         }
334 
335         /// <summary>
336         /// 把list中的框畫到圖片中
337         /// </summary>
338         private void DrawRect()
339         {
340             if (Pic.Image != _initImg)
341                 Pic.Image.Dispose();
342             Pic.Image = PicHelper.GetNewPic(_initImg, (int)(_initImg.Width * _multiple), (int)(_initImg.Height * _multiple));
343             using (Graphics g = Graphics.FromImage(Image))
344             {
345                 foreach (Rectangle item in list)
346                 {
347                     g.DrawRectangle(new Pen(Color.Red), new Rectangle((int)(item.X * _multiple),
348                         (int)(item.Y * _multiple),
349                         (int)(item.Width * _multiple),
350                         (int)(item.Height * _multiple)
351                         ));
352                 }
353             }
354             Pic.Refresh();
355         }
356 
357         private void AdapterDpi()
358         {
359             if (MonitorDPI * _multiple < 10)
360             {
361                 MonitorDPI *= 2;
362             }
363             if (MonitorDPI * _multiple > 20)
364             {
365                 MonitorDPI /= 2;
366             }
367         }
368 
369 
370         
371     }
372 }

下載鏈接:http://download.csdn.net/download/p690075426/10142184


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 定義: 將一個類的介面轉換成客戶希望的另外一個介面。適配器模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。 角色: 目標(Target)角色:這就是所期待得到的介面,也就是這類的介面是符合我們要求的。 源(Adapee)角色:我們要使用的介面,但是這個介面不符合我們的要求,也就是現在需 ...
  • 參考Spring Cloud官方文檔第13、14、15章 13. Circuit Breaker: Hystrix Clients Netflix提供了一個叫Hystrix的類庫,它實現了斷路器模式。在微服務架構中,通常一個微服務會調用多個其他的微服務。一個相對低層級的服務失敗可能造成上層應用的級聯 ...
  • 2017年11月底開始python的學習。選擇python 3.6。 賬號登陸的粗糙實現。 ...
  • 功能 1.天氣預報 2.區域網對戰 展示 java學習群669823128 部分源碼 package game.weather; import java.util.HashMap; public class Weather { /** * @Fields 今天的天氣數據,整體 */ private ...
  • 在大多數大公司,像應用伺服器軟體的安裝、部署都是運維的事情,其實自己去嘗試部署一下,也是有收穫的。 周末在家無聊,正好嘗試了Linux下的rabbitMq安裝過程,做了記錄,希望有用到的人可以做下參考。 安裝環境: Linux: centOS 7.0 mini版 rabbitMq: 3.6.2 查詢 ...
  • 上一篇《Git命令彙總基礎篇》總結了使用Git的基本命令,這一篇作為補充主要給大家講一些平時使用中的技巧和總結 。 學會了這些命令,已經基本解決了使用Git中大部分問題。 1.gitignore 全局配置忽略文件 git config --global core.excludesfile ~/.gi ...
  • 題目描述 永無鄉包含 n 座島,編號從 1 到 n,每座島都有自己的獨一無二的重要度,按照重要度可 以將這 n 座島排名,名次用 1 到 n 來表示。某些島之間由巨大的橋連接,通過橋可以從一個島 到達另一個島。如果從島 a 出發經過若幹座(含 0 座)橋可以到達島 b,則稱島 a 和島 b 是連 通 ...
  • S#語言的最全能類型——字元串(對應C#的String),可用於表示文本內容,如"S#公式是很有特色"等。S#的字元串輸入格式有三種:"xxxxx",@"xxxxx"和'xxxxx'。在S#語言設計時字元串的地位是很高的,系統把它也看成是“程式即數據、數據即程式”的全能表達方式之一。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...