星期二, 7月 27, 2021

紙張輸出內容頁方向

產線同事跑來告知,印表機紙張輸出內容頁方向異常,到現場後才搞清楚,原來是處理完卡紙後,突然意識到說,紙張輸出後內容頁應該要朝上,但是現在是空白頁朝上,當下是一頭霧水,因為從來沒有注意過這件事情

同事認定正常情況,輸出後內容頁朝上 

紙張輸出內容頁方向-2

找其他同型號印表機確認後,確認預設情況是內容頁朝下,如下圖

印表機出紙-1

星期六, 7月 24, 2021

[C#] ContextMenuStrip

根據該篇 ContextMenuStrip 類別 的練習,以 MenuStrip + ContextMenuStrip 為主,不會紀錄 ToolStrip 使用方式,該官方範例會說明 ContextMenuStrip 使用方式,並把 ContextMenuStrip 綁上 MenuStrip 使用
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace ContextMenuStripSample
{
    public partial class Form1 : Form
    {
        private ContextMenuStrip fruitContextMenuStrip;

        public Form1()
        {
            InitializeComponent();

            fruitContextMenuStrip = new ContextMenuStrip();
            fruitContextMenuStrip.Opening += FruitContextMenuStrip_Opening;
            this.ContextMenuStrip = fruitContextMenuStrip;

            ButtonInit();
            MenuStripInit();

        }

        private void ButtonInit()
        {
            Button b = new Button();
            b.Location = new Point(60, 60);
            this.Controls.Add(b);
            b.ContextMenuStrip = fruitContextMenuStrip;
        }

        private void MenuStripInit()
        {
            MenuStrip ms = new MenuStrip();
            ToolStripMenuItem fruitToolStripMenuItem = new ToolStripMenuItem("Fruit", null, null, "Fruit");
            ms.Items.Add(fruitToolStripMenuItem);

            ms.Dock = DockStyle.Top;

            // MenuStrip.Fruit 選項透過 ContextMenuStrip 來顯示
            fruitToolStripMenuItem.DropDown = fruitContextMenuStrip;

            this.Controls.Add(ms);
        }

        private void FruitContextMenuStrip_Opening(object sender, CancelEventArgs e)
        {

            Control ctl = fruitContextMenuStrip.SourceControl as Control;
            // 判斷 ToolStripDropDownItem 會包含 ToolStripMenuItem
            ToolStripDropDownItem tsi = fruitContextMenuStrip.OwnerItem as ToolStripDropDownItem;

            fruitContextMenuStrip.Items.Clear();

            // Check the source control first.
            if (ctl != null)
            {
                fruitContextMenuStrip.Items.Add("右鍵使用 ContextMenuStrip");
                fruitContextMenuStrip.Items.Add("Source:" + ctl.GetType().ToString());
            }
            else if (tsi != null)
            {
                // Add custom item (ToolStripDropDownButton or ToolStripMenuItem)
                fruitContextMenuStrip.Items.Add("點選 MenuStrip");
                fruitContextMenuStrip.Items.Add("Source:" + tsi.GetType().ToString());
            }

            // 原來分隔線可以直接用文字 - 代表
            fruitContextMenuStrip.Items.Add("-");
            fruitContextMenuStrip.Items.Add(new ToolStripSeparator());

            ToolStripMenuItem CustomeItem = new ToolStripMenuItem();
            CustomeItem.Click += Item_Click;

            fruitContextMenuStrip.Items.Add("Custom", null, Item_Click);
            fruitContextMenuStrip.Items.Add("Apples" , null , Item_Click);
            fruitContextMenuStrip.Items.Add("Oranges" , null , Item_Click);
            fruitContextMenuStrip.Items.Add("Pears" , null , Item_Click);

            // Set Cancel to false. It is optimized to true based on empty entry.
            // e.Cancel = true 的話,MenuStrip 的 ContextMenuStrip 就不會顯示啦
            e.Cancel = false;
        }

        private void Item_Click(object sender, EventArgs e)
        {
            MessageBox.Show((sender as ToolStripMenuItem).Text);
        }
    }
}
以前都是每一個 ToolStripMenuItem 都要單獨產生後去綁定 Click 事件,該練習時才發現說,有一個多載方法可以直接傳進去,小發現

[C#] ContextMenuStrip-3

點選 MenuStrip

[C#] ContextMenuStrip-1

使用 ContextMenuStrip

[C#] ContextMenuStrip-2


星期五, 7月 23, 2021

[C#] 繪製-多邊形

公司內有使用到 FillPolygon 來繪製圖型,拿官方範例 - Graphics.FillPolygon 方法 來了解

C# Code
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace GraphicsSample
{
    public partial class FrmFillPolygon : Form
    {
        public FrmFillPolygon()
        {
            InitializeComponent();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            FillPolygonWinding(e);
        }

        public void FillPolygonWinding(PaintEventArgs e)
        {
            PointF point1 = new PointF(50.0F, 50.0F);
            PointF point2 = new PointF(100.0F, 25.0F);
            PointF point3 = new PointF(200.0F, 5.0F);
            PointF point4 = new PointF(250.0F, 50.0F); 
            PointF point5 = new PointF(300.0F, 100.0F);
            PointF point6 = new PointF(350.0F, 200.0F);
            PointF point7 = new PointF(250.0F, 250.0F);
            PointF[] curvePoints = { point1, point2, point3, point4, point5, point6, point7 };

            FillMode fillMode = FillMode.Winding;

            e.Graphics.FillPolygon(Brushes.LightBlue, curvePoints, fillMode);
        }
    }
}
範例筆記
  • [250,50] 和 [300,100] 個人感覺剛好形成一條直線,導致 [250,50] 沒有很明顯
  • 該範例設定 FillMode 其實看不出效果
[C#] 繪製-多邊形

星期二, 7月 20, 2021

[EF] edmx 實體容器名稱

發生需要重建 edmx 的情況,但重建後一直無法使用該 DbContext,查才發現引用是看 [實體容器名稱] 屬性名稱,而不是 edmx 檔案名稱,但該 DbContext 是 Entity

[EF] edmx 實體容器名稱-0

嘗試修正 [實體容器名稱] 時,竟然出現該錯誤訊息

[EF] edmx 實體容器名稱-1

再探發現,是連線字串造成的,先暫時把連線字串隱藏起來,就可以更正實體容器名稱

[EF] edmx 實體容器名稱-3

沒想到改個名稱也有坑可以踩

星期一, 7月 19, 2021

[EF] Schema specified is not valid. - 資料型態不一致

在 edmx 上把 model property 改為自訂 enum 後執行,發生下列錯誤訊息
System.Data.Entity.Core.MetadataException: Schema specified is not valid. Errors: No corresponding object layer type could be found for the conceptual type 'Namespace.EnumName'. The following information may be useful in resolving the previous error: The underlying type of CLR enumeration type does not match the underlying type of EDM enumeration type.
[EF] Schema specified is not valid.-1 

 檢查 Table 欄位資料型態 和 自訂 enum 發現
  • Table 欄位資料形態為 tinyint
  • 自訂 enum 並沒有特別宣告繼承型別,預設為 int
兩者資料型別對應不一致,把自訂 enum 明確宣告繼承至 byte 就解決該問題

星期四, 7月 15, 2021

[VS] 檢視空白區

可能人年紀漸漸增長,手會抖而不自知,最近常常按到 [檢視空白區] 的快捷鍵,然後又要去 Google 如何取消,紀錄一下

從下圖可以看見空白區有點點點的符號顯示
 
[VS] 檢視空白區-1

在 編輯 => 進階 => 檢視空白區,在這進行取消

[VS] 檢視空白區-2

不要再跑去選項內找啦,Orz

星期五, 7月 09, 2021

[C#] 透過 ToolStripControlHost 自訂 ToolStripItem

根據 作法:使用 ToolStripControlHost 包裝 Windows Forms 控制項 的筆記,該篇是把 MonthCalendar 標準控件塞進 ToolStripItem 內,有註冊公開的 DateChanged 事件來把結果傳回 TextBox 上,效果如下圖

[C#] 透過 ToolStripControlHost 自訂 ToolStripItem

建構子是最重要部分,因為要把 MonthCalendar 傳給 ToolStripControlHost
using System;
using System.Windows.Forms;

namespace UCToolStripControlHost
{
    public class ToolStripMonthCalendar : ToolStripControlHost
    {
        // 把 MonthCalendar 傳進 ToolStripControlHost 建構子
        public ToolStripMonthCalendar() : base(new MonthCalendar())
        {

        }

        public MonthCalendar MonthCalendarControl
        {
            get
            {
                return Control as MonthCalendar;
            }
        }

        // 公開 FirstDayOfWeek 屬性
        public Day FirstDayOfWeek
        {
            get
            {
                return MonthCalendarControl.FirstDayOfWeek;
            }
            set 
            {
                MonthCalendarControl.FirstDayOfWeek = value;
            }
        }

        // 公開 AddBoldedDate 方法
        public void AddBoldedDate(DateTime dateToBold)
        {
            MonthCalendarControl.AddBoldedDate(dateToBold);
        }

        // 公開 DateChanged 事件
        public event DateRangeEventHandler DateChanged
        {
            add { MonthCalendarControl.DateChanged += value; }
            remove { MonthCalendarControl.DateChanged -= value; }
        }
    }
}
在 Form 內把自訂的 ToolStripMonthCalendar 塞進 MenuStrip 上使用,MenuStrip 和 ToolStripMenuItem 是直接拖曳建立上 Form 的
using System;
using System.Windows.Forms;

namespace UCToolStripControlHost
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            ToolStripMonthCalendar monthCalendar = new ToolStripMonthCalendar();
            toolStripMenuItem1.DropDownItems.Add(monthCalendar);
            monthCalendar.DateChanged += (sender, e) =>
            {
                txtStartDate.Text = e.Start.ToString();
            };
        }
    }
}

星期三, 7月 07, 2021

[C#] 控件智能標籤 - 設定屬性值

[C#] 控件智能標籤 內有筆記該重點 - 更新要透過 PropertyDescriptor 來完成 
When a property or method in the class derived from DesignerActionList changes the state of the associated control, these changes should not be made by direct setter calls to the component's properties. Instead, such changes should be made through an appropriately created PropertyDescriptor. This indirect approach ensures that smart-tag undo and UI update actions function correctly.
從下圖可以看出,在智能標籤上把 Name 修改為 ChangeName 後,屬性視窗內的 Name 還是 flatButton1,沒有跟著變化
 
[C#] 控件智能標籤-設定屬性值

查 Code 才發現,原來使用方式是透過 Type.GetProperty().SetValue() 來設定屬性值,而不是透過 PropertyDescriptor
 
簡易紀錄
// 異常方式
Type.GetProperty().SetValue();

// 正確方式
TypeDescriptor.GetProperties().SetValue();

星期一, 7月 05, 2021

GodexRT730X - 碳帶安裝

久遠前標籤機出現列印品質問題,一直找不到原因的情況下,只能請廠商來查看,一打開機器就發現碳帶安裝錯誤,錯誤的點在於,不要把碳帶繞過桿子

碳帶正確安裝方式
 
GodexRT730X - 碳帶安裝-1

來張近照,可以看到桿子上有點綠色痕跡

GodexRT730X - 碳帶安裝-2

每次被使用者 call 去現場,都會在腦海裡打架,到底要不要繞過桿子,最後只好再去找其他台確認,乾脆紀錄一下

星期六, 7月 03, 2021

[EF] The entity type is not part of the model for the current context

新增 DContext 時搞烏龍,連線字串內指定 emdx 的 metadata 沒有指定到對的 DbContext,導致執行時就拋出該錯誤訊息
The entity type Type is not part of the model for the current context
[EF] The entity type Type is not part of the model for the current context-1

修正連線字串 edmx metadata 的 csdl、ssdl 和 msl 對應 DbContext 就解決該問題
<connectionStrings>
	<add name="CustomDbContext"
		 connectionString="
			metadata=
				res://*/DbContext.CustomDbContext.csdl| 
				res://*/DbContext.CustomDbContext.ssdl| 
				res://*/DbContext.CustomeDbContext.msl;
				provider=System.Data.SqlClient;
				provider connection string="
				data source=.\SQLInstance;
				initial catalog=DBName;
				User Id=UserID;
				Password=PWD;
				integrated security=False;
				multipleactiveresultsets=True;
				application name=EntityFramework""
		 providerName="System.Data.EntityClient"/>
</connectionStrings>