C#並口熱敏小票印表機列印位元影像包括晶片的寫入

來源:互聯網
上載者:User

標籤:

 

下面是列印所需要調用的代碼:

class LptControl { private string LptStr = "lpt1"; public LptControl(string l_LPT_Str) {  LptStr = l_LPT_Str; } [StructLayout(LayoutKind.Sequential)] private struct OVERLAPPED { int Internal; int InternalHigh; int Offset; int OffSetHigh; int hEvent; }   //調用DLL. [DllImport("kernel32.dll")] private static extern int CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); [DllImport("kernel32.dll")] private static extern bool WriteFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, ref OVERLAPPED lpOverlapped); [DllImport("kernel32.dll")] private static extern bool CloseHandle(int hObject); private int iHandle;   /// <summary> /// 開啟連接埠 /// </summary> /// <returns></returns> public bool Open() { iHandle = CreateFile(LptStr, 0x40000000, 0, 0, 3, 0, 0); // iHandle = CreateFile(LptStr, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);  if (iHandle != -1) { return true; } else { return false; } }  /// <summary> /// 列印字串,通過調用該方法可以列印需要的字串 /// </summary> /// <param name="Mystring"></param> /// <returns></returns> public bool Write(String Mystring) { //如果連接埠為開啟,則提示,開啟,則列印 if (iHandle != -1) { OVERLAPPED x = new OVERLAPPED(); int i = 0; //byte[] mybyte = System.Text.Encoding.Default.GetBytes(Mystring); byte[] mybyte = Encoding.GetEncoding("GB2312").GetBytes(Mystring); bool b = WriteFile(iHandle, mybyte, mybyte.Length, ref i, ref x); return b; } else { throw new Exception("不能串連到印表機!"); } } /// <summary> /// 列印命令,通過參數,可以列印小票印表機的一些命令,比如換行,行間距,列印位元影像等。 /// </summary> /// <param name="mybyte"></param> /// <returns></returns> public bool Write(byte[] mybyte) { //如果連接埠為開啟,則提示,開啟,則列印 if (iHandle != -1) { OVERLAPPED x = new OVERLAPPED(); int i = 0; return WriteFile(iHandle, mybyte, mybyte.Length, ref i, ref x); } else { throw new Exception("不能串連到印表機!"); } }  /// <summary> /// 關閉連接埠 /// </summary> /// <returns></returns> public bool Close() { return CloseHandle(iHandle); }  } 


 

因為我們這裡主要是列印條碼和二維碼,所以以條碼和二維碼為例,寫了一個小的調用程式(這裡把列印圖片的方法貼出來):

 

/// <summary> /// 列印圖片方法 /// </summary> public void PrintOne() { //擷取圖片 Bitmap bmp = new Bitmap(pictureBox1.Image);  //設定字元行間距為n點行 //byte[] data = new byte[] { 0x1B, 0x33, 0x00 }; string send = "" + (char)(27) + (char)(51) + (char)(0); byte[] data = new byte[send.Length]; for (int i = 0; i < send.Length; i++) { data[i] = (byte)send[i]; } lc.Write(data);  data[0] = (byte)‘\x00‘; data[1] = (byte)‘\x00‘; data[2] = (byte)‘\x00‘; // Clear to Zero.  Color pixelColor;   //ESC * m nL nH d1…dk 選擇位元影像模式 // ESC * m nL nH byte[] escBmp = new byte[] { 0x1B, 0x2A, 0x00, 0x00, 0x00 };  escBmp[2] = (byte)‘\x21‘;  //nL, nH escBmp[3] = (byte)(bmp.Width % 256); escBmp[4] = (byte)(bmp.Width / 256);  //循環圖表片像素列印圖片 //迴圈高 for (int i = 0; i < (bmp.Height / 24 + 1); i++) { //設定模式為位元影像模式 lc.Write(escBmp); //迴圈寬 for (int j = 0; j < bmp.Width; j++) { for (int k = 0; k < 24; k++) { if (((i * 24) + k) < bmp.Height) // if within the BMP size { pixelColor = bmp.GetPixel(j, (i * 24) + k); if (pixelColor.R == 0) { data[k / 8] += (byte)(128 >> (k % 8));  } } } //一次寫入一個data,24個像素 lc.Write(data);  data[0] = (byte)‘\x00‘; data[1] = (byte)‘\x00‘; data[2] = (byte)‘\x00‘; // Clear to Zero. }  //換行,列印第二行 byte[] data2 = { 0xA }; lc.Write(data2); } // data lc.Write("\n\n"); }  


 

     

在列印過程中,出現一個比較低級的錯誤,因為小票印表機是並口的,而我電腦是串口的,所以一直遠程在另一台電腦上測試,所以列印出來的圖片中間多了一條橫線,這個問題解決了多半天,因為我一直考慮到是列印圖片中可能少一層迴圈的問題,所以順便把列印圖片的原理整理了一下(之前的迴圈是從網上找到的,感覺應該沒問題就沒有細研究)。下面分享一下我的理解:

這是列印位元影像的命令(每一個印表機都會給出這樣的說明,可以直接下載到的):

1.  ESC* m nL nH d1…dk   選擇位元影像模式

格式:   ASCII: ESC * m nL nH d1…dk

      十進位:  [27] [42] m nL nH d1…dk

    十六進位:  [1BH][2AH] m nL nH d1…dk

說明:

    .設定位元影像方式(用m)、點數(用nL,nH)以及位元影像內容(用dk)。

    .m=0,1,32,33;0≤nL≤255,0≤nH≤3,0≤d≤255。

     k=nL+nH×256(m=0,1);k=(nL+nH×256)×3(m=32,33)。

    .水平方向點數為(nL+nH×256)。

    .如果點數超過一行,超過其最大點數(與選擇的位元影像方式有關,詳      見下表)的部分被忽略。

    .d為位元影像資料位元組,對應位為1則表示該點列印,對應位為0,則  表示該點不列印。(k表示資料個數)

    .m用於選擇位元影像方式。

 

模式

縱向

橫向

點數

解析度

解析度

資料個數(k)

0

8點單密度

8

67  DPI

100  DPI

nL+nH×256

1

8點雙密度

8

67  DPI

200  DPI

nL+nH×256

32

24點單密度

24

200  DPI

100  DPI

(nL+nH×256)×3

33

24點雙密度

24

200  DPI

200  DPI

(nL+nH×256)×3

 

 

 

 

 

 

 

這次用的印表機列印是24點雙密度的,所以我這裡就只解釋下m=33的情況。

從代碼中可以看出,列印圖片過程主要是通過迴圈一點點列印的,通過

lc.Write(data);

迴圈寫入,當然前面的lc.Write(escBmp)主要是些ESC * m三個參數很容易理解就不多解釋了。而data是一個長度為3的byte數組,這個data在列印中起到什麼作用呢?

在印表機m=33的模式縱向每次是列印24個點,也就是說,而byte為8個位元組,所以需要3個byte類型的樹才能完成模式為24點雙密碼的位元影像列印方式,通過三個字元來平湊一個像素寬24個像素長的圖片,然後迴圈寬度,來列印圖片寬度大小24個像素高度的圖片,在通過每次迴圈24個像素的高度,最終列印出完成的圖片。

需要列印的圖片:

 

第一次迴圈先是高位24像素

 

然後把寬度分解開,迴圈每一像素的寬度,然後列印每一像素寬度的圖片:

舉個例子,假設數組data[d1,d2,d3],d1= 00000111,d2=11111111,d3 =11111111,所以列印出的一個像素寬,24像素高的圖片為:

 

最終通過迴圈寬度與高度,把最終的位元影像畫出來。

這裡我舉的是24點密度的例子,通過,如果您有興趣研究的話,也經常看到這樣的代碼:

 

 

for (int i = 0; i < ((bmp.Height + 7) / 8); i++) { _serialPort.Write(escBmp, 0, escBmp.Length);  for (int j = 0; j < bmp.Width; j++) { for (int k = 0; k < 8; k++) { if (((i * 8) + k) < bmp.Height) // if within the BMP size { pixelColor = bmp.GetPixel(j, (i * 8) + k); if (pixelColor.R == 0) { data[0] += (byte)(128 >> k); } } }  _serialPort.Write(data, 0, 1); data[0] = (byte)‘\x00‘; // Clear to Zero. } 


 

這個很明顯就是8點密度的模式,所以他的data長度為1,即需要8個位元組就夠了。

列印出的效果還是很不錯的。

C#並口熱敏小票印表機列印位元影像包括晶片的寫入

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.