截圖小工具開發筆記

来源:https://www.cnblogs.com/agoodlife/archive/2019/05/11/10849653.html
-Advertisement-
Play Games

一、開發環境及工具 Windows 7 系統,開發軟體為Microsoft Visual Studio Ultimate 2012 二、實現的功能 屏幕截屏,保存到圖片或者保存到剪切板。截屏範圍可以隨意移動或者改變大小,自由度很高。先預覽一下效果: 三、實現原理 共2個窗體,1個是主窗體,主要功能進 ...


一、開發環境及工具

Windows 7 系統,開發軟體為Microsoft Visual Studio Ultimate 2012

二、實現的功能

屏幕截屏,保存到圖片或者保存到剪切板。截屏範圍可以隨意移動或者改變大小,自由度很高。先預覽一下效果:

三、實現原理

2個窗體,1個是主窗體,主要功能進行熱鍵設置,抓取屏幕到圖片傳給另一個窗體,另一個窗體對傳過來的圖片繼續截取等操作。

四、開發手記

1.新建winform項目

2.主界面設計如圖:

窗體主要屬性設置如下:

//視窗樣式
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
//視窗圖標
  this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
//禁止最大化            
this.MaximizeBox = false;
//視窗名稱
 this.Name = "PicCut";
//視窗初始位置為屏幕中心
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
//視窗標題為“截圖設置”
this.Text = "截圖設置";
//視窗浮在所有視窗上面
 this.TopMost = true;

 

 

此視窗內主要包括2label控制項,1ComboBox1PictureBox,擺放位置如上圖。label用於顯示文字說明;ComboBox用於顯示熱鍵09個數字供選擇;PictureBox用於顯示二維碼圖片。

3.主界面的主要功能是對熱鍵進行設置,同時我們程式運行,該界面自動最小化到托盤,雙擊進行截圖,有機顯示上述主界面進行設置,設置完畢可以最小化自動到托盤,點擊關閉程式會自動退出。

 

1)自動到托盤

主界面拖入“notifyIcon”,主要屬性設置如下圖,其中Text是滑鼠滑動到拖盤區域圖標上的提示;Icon是托盤圖標;Visible設置為false,預設不顯示托盤區域圖標。

 

 

主要程式代碼。窗體載入時,最小化窗體,同時設置ComboBox空間的預設值。

private void PicCut_Load(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized; NumberCbox.SelectedIndex = CutPicSet.Default.KeyNumber; }

 

視窗大小發生變化時,如果視窗最小化,隱藏當前窗體,托盤區域顯示圖標。

private void PicCut_SizeChanged(object sender, EventArgs e)
 {
           if (this.WindowState == FormWindowState.Minimized)
            {
                 this.Hide();
                MinNot.Visible = true;   
            }
 }

 

上述兩段代碼實現了,程式開始運行時候,視窗最小化隱藏,同時托盤區域顯示圖標。

(2)托盤圖標左鍵雙擊進行截圖操作

private void MinNot_MouseDoubleClick(object sender, MouseEventArgs e)
{
      if (e.Button==MouseButtons.Left)
     {
//顯示截圖窗體
ShowCutPic(); } }

 

ShowCutPic函數:
protected void ShowCutPic()
        {
            // 創建的空白圖片和屏幕大小一樣大的圖片
            Bitmap CatchBmp = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);            
            // 我們可以通過Graphics這個類在這個空白圖片上畫圖
            Graphics g = Graphics.FromImage(CatchBmp);
            // 把屏幕圖片拷貝到我們創建的空白圖片 CatchBmp中
            g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height));
            //這個我們截圖的窗體創建截圖窗體
            cutter = new CutPic();
             // 截圖窗體的圖片屬性設置我們剛纔新建的圖片;
            cutter.Image = CatchBmp;
           //顯示窗體
            cutter.ShowDialog();
        }

 

 

3)托盤圖標右鍵單擊顯示界面設置

 private void MinNot_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button== MouseButtons.Right)
            {
//顯示主窗體
                this.Show();
//隱藏托盤圖標
                MinNot.Visible = false;
//當前視窗普通設置
                this.WindowState = FormWindowState.Normal;               
            }
                   
        }

 

4)熱鍵設置

/// <summary>
        /// 如果函數執行成功,返回值不為0。
        /// 如果函數執行失敗,返回值為0。要得到擴展錯誤信息,調用GetLastError。
        /// </summary>
        /// <param name="hWnd">要定義熱鍵的視窗的句柄</param>
        /// <param name="id">定義熱鍵ID(不能與其它ID重覆)</param>
        /// <param name="fsModifiers">標識熱鍵是否在按Alt、Ctrl、Shift、Windows等鍵時才會生效</param>
        /// <param name="vk">定義熱鍵的內容</param>
        /// <returns></returns>
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, Keys vk);

        /// <summary>
        /// 註銷熱鍵
        /// </summary>
        /// <param name="hWnd">要取消熱鍵的視窗的句柄</param>
        /// <param name="id">要取消熱鍵的ID</param>
        /// <returns></returns>
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        /// <summary>
        /// 輔助鍵名稱。
        /// Alt, Ctrl, Shift, WindowsKey
        /// </summary>
        [Flags()]
        public enum KeyModifiers { None = 0, Alt = 1, Ctrl = 2, Shift = 4, WindowsKey = 8 }

        /// <summary>
        /// 註冊熱鍵
        /// </summary>
        /// <param name="hwnd">視窗句柄</param>
        /// <param name="hotKey_id">熱鍵ID</param>
        /// <param name="keyModifiers">組合鍵</param>
        /// <param name="key">熱鍵</param>
        public static void RegHotKey(IntPtr hwnd, int hotKeyId, KeyModifiers keyModifiers, Keys key)
        {
            if (!RegisterHotKey(hwnd, hotKeyId, keyModifiers, key))
            {
                int errorCode = Marshal.GetLastWin32Error();
                if (errorCode == 1409)
                {
                    MessageBox.Show("熱鍵被占用 !");
                }
                else
                {
                    MessageBox.Show("註冊熱鍵失敗!錯誤代碼:" + errorCode);
                }
            }
        }

        /// <summary>
        /// 註銷熱鍵
        /// </summary>
        /// <param name="hwnd">視窗句柄</param>
        /// <param name="hotKey_id">熱鍵ID</param>
        public static void UnRegHotKey(IntPtr hwnd, int hotKeyId)
        {
            //註銷指定的熱鍵
            UnregisterHotKey(hwnd, hotKeyId);
        }
private const int WM_HOTKEY = 0x312; //視窗消息-熱鍵
        private const int WM_CREATE = 0x1; //視窗消息-創建
        private const int WM_DESTROY = 0x2; //視窗消息-銷毀
        private const int Space = 0x3572; //熱鍵ID
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            switch (m.Msg)
            {
                case WM_HOTKEY: //視窗消息-熱鍵ID
                    switch (m.WParam.ToInt32())
                    {
                        case Space: //熱鍵ID
//按下熱鍵顯示截圖窗體
                            ShowCutPic();
                            break;
                        default:
                            break;
                    }
                    break;
                case WM_CREATE: //視窗消息-創建
                    SetHotKey(CutPicSet.Default.KeyNumber);
                    break;
                case WM_DESTROY: //視窗消息-銷毀
                    UnRegHotKey(Handle, Space); //銷毀熱鍵
                    break;
                default:
                    break;
            }
        }

        public void SetHotKey(int keynumber)
        {
            if (keynumber == 0)
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D0);
            }
            else if (keynumber == 1)
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D1);
            }
            else if (keynumber == 2)
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D2);
            }
            else if (keynumber == 3)
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D3);
            }
            else if (keynumber == 4)
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D4);
            }
            else if (keynumber == 5)
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D5);
            }
            else if (keynumber == 6)
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D6);
            }
            else if (keynumber == 7)
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D7);
            }
            else if (keynumber == 8)
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D8);
            }
            else
            {
                RegHotKey(Handle, Space, KeyModifiers.Ctrl, Keys.D9);
            }
        }

 

 5)圖形熱鍵設置

 private void NumberCbox_SelectedIndexChanged(object sender, EventArgs e)
        {
//把配置文件設置NumberCbox的選擇值
            CutPicSet.Default.KeyNumber = NumberCbox.SelectedIndex;
            CutPicSet.Default.Save();
//先卸載原來註冊的熱鍵
            UnRegHotKey(Handle, Space);
//從新設置選擇的熱鍵
            SetHotKey(NumberCbox.SelectedIndex);
        }

 

4、截圖界面設計

新建窗體CutPic,名稱與之前的名稱相對應,主要屬性設置如下:

Name:CutPic

WindowState:Maximized

TopMost:true

FormBorderStyle:None

5、截圖功能實現

主要代碼如下:

 private Point m_ptStart;        //起始點位置
        private Point m_ptCurrent;      //當前滑鼠位置
        private Point m_ptTempForMove;  //移動選框的時候臨時用
        private Rectangle m_rectClip;   //限定滑鼠活動的區域
        private Rectangle[] m_rectDots = new Rectangle[8];  //八個控制點
        protected bool m_bMoving;
        protected bool m_bChangeWidth;
        protected bool m_bChangeHeight;
        protected bool m_bMouseHover;
        private bool _IsDrawed; /// 獲取當前是否已經選擇區域
        private Image _Image;
        ///
        /// 要裁剪的圖像
        ///
        [Description("要裁剪的圖像"), Category("Customs")]
        public Image Image
        {
            get { return _Image; }
            set
            {
                if (value == this._Image) return;
                _Image = value;
             //   this.Clear();
            }
        }
        private Color _MaskColor = Color.FromArgb(125, 0, 0, 0);
        ///
        /// 遮罩顏色
        ///
        [Description("遮罩顏色"), Category("Customs")]
        public Color MaskColor
        {
            get { return _MaskColor; }
            set
            {
                if (_MaskColor == value) return;
                _MaskColor = value;
                if (this._Image != null) this.Invalidate();
            }
        }
        private Rectangle _SelectedRectangle;/// 獲取或設置懸著區域
       
        public CutPic()
        {
            SetStyle(ControlStyles.UserPaint, true);  
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.  
            SetStyle(ControlStyles.DoubleBuffer, true); // 雙緩衝  

            InitializeComponent();
        }

        private void CutPic_MouseDown(object sender, MouseEventArgs e)
        {
            if (this._Image == null)
            {
                return;//Image屬性null或者已經鎖定選擇 直接返回
            }
            m_ptStart = e.Location;
            m_bChangeHeight = true;
            m_bChangeWidth = true;

            //判斷若不在限定範圍內操作 返回
            m_rectClip = this.DisplayRectangle;
                Size sz = this.Size;
                sz = this.Size;                
                m_rectClip.Intersect(new Rectangle(Point.Empty, sz));
                m_rectClip.Width++; m_rectClip.Height++;
                Cursor.Clip = RectangleToScreen(m_rectClip);
            

            if (ToolsPanel.Visible==true)
            {
                ToolsPanel.Visible = false;
            }
            //如果 已經選擇區域 若滑鼠點下 判斷是否在控制頂點上
            if (this._IsDrawed)
            {
                this._IsDrawed = false; //預設表示 要更改選取設置 清楚IsDrawed屬性
                if (m_rectDots[0].Contains(e.Location))
                {
                    m_ptStart.X = this._SelectedRectangle.Right;
                    m_ptStart.Y = this._SelectedRectangle.Bottom;
                }
                else if (m_rectDots[1].Contains(e.Location))
                {
                    m_ptStart.Y = this._SelectedRectangle.Bottom;
                    m_bChangeWidth = false;
                }
                else if (m_rectDots[2].Contains(e.Location))
                {
                    m_ptStart.X = this._SelectedRectangle.X;
                    m_ptStart.Y = this._SelectedRectangle.Bottom;
                }
                else if (m_rectDots[3].Contains(e.Location))
                {
                    m_ptStart.X = this._SelectedRectangle.Right;
                    m_bChangeHeight = false;
                }
                else if (m_rectDots[4].Contains(e.Location))
                {
                    m_ptStart.X = this._SelectedRectangle.X;
                    m_bChangeHeight = false;
                }
                else if (m_rectDots[5].Contains(e.Location))
                {
                    m_ptStart.X = this._SelectedRectangle.Right;
                    m_ptStart.Y = this._SelectedRectangle.Y;
                }
                else if (m_rectDots[6].Contains(e.Location))
                {
                    m_ptStart.Y = this._SelectedRectangle.Y;
                    m_bChangeWidth = false;
                }
                else if (m_rectDots[7].Contains(e.Location))
                {
                    m_ptStart = this._SelectedRectangle.Location;
                }
                else if (this._SelectedRectangle.Contains(e.Location))
                {
                    m_bMoving = true;
                    m_bChangeWidth = false;
                    m_bChangeHeight = false;
                }
                else { this._IsDrawed = true; }   //若以上條件不成立 表示不需要更改設置
            }
        }

        private void CutPic_MouseClick(object sender, MouseEventArgs e)
        {
            if (MouseButtons.Right==e.Button)
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        private void CutPic_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            if (_Image!=null)
            {
                  g.DrawImage(this._Image,0,0,this._Image.Width,this._Image.Height);//原圖
                  using (SolidBrush sb = new SolidBrush(this._MaskColor))
                  {
                      g.FillRectangle(sb, this.ClientRectangle);//遮罩
                  }
                  if (!this._SelectedRectangle.IsEmpty)
                      this.DrawSelectedRectangle(g);//選框
            }
            SetPanleLocation();
        }

        private void CutPic_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < 8; i++)
            {
                m_rectDots[i].Size = new Size(5, 5);
            }        
                          
            m_ptTempForMove = this.DisplayRectangle.Location;
          
        }

        private void CutPic_MouseMove(object sender, MouseEventArgs e)
        {
            m_ptCurrent = e.Location;
            if (this._Image == null)
            {
                return;
            }
            if (this._IsDrawed)
            {//如果已經繪製 移動過程中判斷是否需要設置滑鼠樣式
                this.SetCursorStyle(e.Location);
            }
            else if (e.Button == MouseButtons.Left)
            {//否則可能表示在選擇區域或重置大小
                if (m_bChangeWidth)
                {//是否允許選區寬度改變 如重置大小時候 拉動上邊和下邊中點時候
                    this._SelectedRectangle.X = e.Location.X > m_ptStart.X ? m_ptStart.X : e.Location.X;
                    this._SelectedRectangle.Width = Math.Abs(e.Location.X - m_ptStart.X);
                }
                if (m_bChangeHeight)
                {
                    this._SelectedRectangle.Y = e.Location.Y > m_ptStart.Y ? m_ptStart.Y : e.Location.Y;
                    this._SelectedRectangle.Height = Math.Abs(e.Location.Y - m_ptStart.Y);
                }
                if (m_bMoving)
                {//如果是移動選區 判斷選區移動範圍
                    int tempX = m_ptTempForMove.X + e.X - m_ptStart.X;
                    int tempY = m_ptTempForMove.Y + e.Y - m_ptStart.Y;
                    
                    if (tempX < 0) tempX = 0;
                        if (tempY < 0) tempY = 0;
                        if (this._SelectedRectangle.Width + tempX >= m_rectClip.Width) tempX = m_rectClip.Width - this._SelectedRectangle.Width - 1;
                        if (this._SelectedRectangle.Height + tempY >= m_rectClip.Height) tempY = m_rectClip.Height - this._SelectedRectangle.Height - 1;
                   
                    this._SelectedRectangle.X = tempX;
                    this._SelectedRectangle.Y = tempY;
                }
                this.Invalidate();
            }
            else if (!this._IsDrawed)
            {
                this.Invalidate();//否則 在需要繪製放大鏡並且還沒有選好區域同時 都重繪
            }
        }
        ///
        /// 判斷滑鼠當前位置顯示樣式
        ///
        /// 滑鼠坐標
        protected virtual void SetCursorStyle(Point pt)
        {
            if (m_rectDots[0].Contains(pt) || m_rectDots[7].Contains(pt))
                this.Cursor = Cursors.SizeNWSE;
            else if (m_rectDots[1].Contains(pt) || m_rectDots[6].Contains(pt))
                this.Cursor = Cursors.SizeNS;
            else if (m_rectDots[2].Contains(pt) || m_rectDots[5].Contains(pt))
                this.Cursor = Cursors.SizeNESW;
            else if (m_rectDots[3].Contains(pt) || m_rectDots[4].Contains(pt))
                this.Cursor = Cursors.SizeWE;
            else if (this._SelectedRectangle.Contains(pt))
                this.Cursor = Cursors.SizeAll;
            else
                this.Cursor = Cursors.Default;
        }

        private void CutPic_MouseUp(object sender, MouseEventArgs e)
        {
            this._IsDrawed = !this._SelectedRectangle.IsEmpty;
            m_ptTempForMove = this._SelectedRectangle.Location;
            m_bMoving = false;
            m_bChangeWidth = false;
            m_bChangeHeight = false;
            Cursor.Clip = Rectangle.Empty;
            ToolsPanel.Visible = true;
            this.Invalidate();

            
           
        }

        public void SetPanleLocation()
        {
            ToolsPanel.Left = this._SelectedRectangle.Left + this._SelectedRectangle.Width - ToolsPanel.Width;
            ToolsPanel.Top =  this._SelectedRectangle.Top+this._SelectedRectangle.Height+5;
        }


        ///
        /// 繪製選框
        ///
        /// 繪圖錶面
        protected virtual void DrawSelectedRectangle(Graphics g)
        {
            m_rectDots[0].Y = m_rectDots[1].Y = m_rectDots[2].Y = this._SelectedRectangle.Y - 2;
            m_rectDots[5].Y = m_rectDots[6].Y = m_rectDots[7].Y = this._SelectedRectangle.Bottom - 2;
            m_rectDots[0].X = m_rectDots[3].X = m_rectDots[5].X = this._SelectedRectangle.X - 2;
            m_rectDots[2].X = m_rectDots[4].X = m_rectDots[7].X = this._SelectedRectangle.Right - 2;
            m_rectDots[3].Y = m_rectDots[4].Y = this._SelectedRectangle.Y + this._SelectedRectangle.Height / 2 - 2;
            m_rectDots[1].X = m_rectDots[6].X = this._SelectedRectangle.X + this._SelectedRectangle.Width / 2 - 2;

            g.DrawImage(this._Image, this._SelectedRectangle, this._SelectedRectangle, GraphicsUnit.Pixel);
            g.DrawRectangle(Pens.Cyan, this._SelectedRectangle.Left, this._SelectedRectangle.Top, this._SelectedRectangle.Width - 1, this._SelectedRectangle.Height - 1);
            foreach (Rectangle rect in m_rectDots)
                g.FillRectangle(Brushes.Yellow, rect);
            string str = string.Format("X:{0} Y:{1} W:{2} H:{3}",
                this._SelectedRectangle.Left, this._SelectedRectangle.Top, this._SelectedRectangle.Width, this._SelectedRectangle.Height);
            Size szStr = g.MeasureString(str, this.Font).ToSize();
            Point ptStr = new Point(this._SelectedRectangle.Left, this._SelectedRectangle.Top - szStr.Height - 5);
            if (ptStr.Y < 0) ptStr.Y = this._SelectedRectangle.Top + 5;
            if (ptStr.X + szStr.Width > this.Width) ptStr.X = this.Width - szStr.Width;
            using (SolidBrush sb = new SolidBrush(Color.FromArgb(125, 0, 0, 0)))
            {
                g.FillRectangle(sb, new Rectangle(ptStr, szStr));
                g.DrawString(str, this.Font, Brushes.White, ptStr);
            }
        }

        private void SaveBT_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.FileName = DateTime.Now.ToString("yyyyMMddhhmmss");
            saveFileDialog.Filter = "png|*.png|bmp|*.bmp|jpg|*.jpg|gif|*.gif";
            if (saveFileDialog.ShowDialog() != DialogResult.Cancel)
            {
                System.Drawing.Rectangle cropArea = new System.Drawing.Rectangle(_SelectedRectangle.X, _SelectedRectangle.Y, _SelectedRectangle.Width, _SelectedRectangle.Height);
                Bitmap bmpImage = new Bitmap(this._Image);
                Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
                bmpCrop.Save(saveFileDialog.FileName);
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
            else
            {
                this.Focus();
            }
        }
       

        private void CutPic_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (this._SelectedRectangle.Contains(e.Location))
            {
                //複製圖片到剪切板
                System.Drawing.Rectangle cropArea = new System.Drawing.Rectangle(_SelectedRectangle.X, _SelectedRectangle.Y, _SelectedRectangle.Width, _SelectedRectangle.Height);
                Bitmap bmpImage = new Bitmap(this._Image);
                Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
                Clipboard.SetImage(bmpCrop);
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }
//如果按下ESC鍵退出截圖功能
        private void CutPic_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyValue==27)
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

 

這樣截圖功能就已經實現了。源代碼下載,請點擊

 


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

-Advertisement-
Play Games
更多相關文章
  • 1.複習 2.匿名函數 3.作用域 4.函數式編程 4.map函數 5.filter函數 6.reduce函數 7.小結 8.內置函數 ...
  • 美食排行榜網站上線後,為了快速提升流量,需要製造一個引流機會。 我的想法是開闢一個專欄,按照菜品和地區,讓用戶自發投票給自己喜歡的餐館,最終形成一個年度/月度 等的美食排行榜 比如 成都川菜美食排行榜 這個頁面,目前是按照數據入庫的先後時間排序,並不是用戶真實的排行,怎麼才能做到真實排行呢? 這就需 ...
  • 基於flask的網頁聊天室(三) 前言 繼續上一次的內容,今天完成了csrf防禦的添加,用戶頭像的存儲以及用戶的登錄狀態 具體內容 首先是添加csrf的防禦,為整個app添加防禦: from flask_wtf.csrf import CSRFProtect CSRFProtect(app) 這個添 ...
  • 1.Equals 很多人對equals方法的用法有些模糊,這裡來為大家梳理下: 字元串中的equals方法,該方法用來判斷兩個字元串的內容是否相同。 例1: 從例1中我們可以看出,兩個字元串之間的比較,無論用”==”號還是equals來進行,只要內容相同,結果就為True,內容不同,結果就為Fals ...
  • [TOC] 手寫數字識別流程 MNIST手寫數字集7000 10張圖片 60k張圖片訓練,10k張圖片測試 每張圖片是28\ 28,如果是彩色圖片是28\ 28\ 3 0 255表示圖片的灰度值,0表示純白,255表示純黑 打平28 28的矩陣,得到28\ 28=784的向量 對於b張圖片得到[b, ...
  • 前置知識: 棧 隊列 單調棧 思考這樣一個問題:給定一個數列,詢問每一個數左邊的第一個比它小的數。 暴力的做法是:記錄下所有讀進來的數,然後,每次向前查找,預計時間複雜度O(n2),而且容易被卡。 仔細思考一下,可以發現,這個做法之所以效率低下,是因為每一次都重覆查找了許多肯定不是最優解的元素。很明 ...
  • 基於ASP.NET MVC 實現layui富文本編輯器圖片展示 ...
  • Modbus Rtu的實現與Modbus Tcp的實現類似 C#ModBus Tcp的學習及Master的實現 我們還是需要借用一個開源庫NModbus4,在vs中.打開NuGet管理器.安裝NModbus4 具體實現,具體實現與之前的Modbus Tcp的實現類似 ,只是在實例化master時將T ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...