赞
踩
Unicode软件开发时需要遵循以下规则:使用中可尽量使用自适应版本。
Unicode软件开发: a)微软的软件工程现在默认使用Unicode(UTF16位小端),尤其是Windows图形化软件工程。 b)Unicode软件工程下,常量的定义使用L"xxxx",ANSI使用“XXX”; c)微软的跟字符串打交道的API都会定义两套:例如: #ifdef UNICODE #define SetDlgItemText SetDlgItemTextW #else #define SetDlgItemText SetDlgItemTextA #endif // !UNICODE d)C语言库函数跟字符串打交道的,全部重写Unicode版本。 比如: char *strcat( char *strDestination, const char *strSource ); wchar_t *wcscat( wchar_t *strDestination, const wchar_t *strSource );
TCHAR类型:
a)窄字符串:typedef const char* LPCSTR;
b)宽字符串:typedef const wchar_t* LPCWSTR;
c)自适应字符串:typedef TCHAR* LPCTSTR;
#ifdef UNICODE // r_winnt
typedef wchar_t TCHAR;
typedef const wchar_t* LPCTSTR;
#else
typedef char TCHAR;
typedef const char* LPCTSTR;
#endif
主函数Main.cpp 主要是把ANSI和UTF8编码转换成为Unicode16
#define _CRT_SECURE_NO_WARNINGS #include<windows.h> #include"resource.h" #include<stdio.h> void ConvertBig(LPSTR p); bool CheckUtf8(LPCSTR p); wchar_t* ANSIToUnicode(const char* str); wchar_t* UTF8ToUnicode(const char* str); void ParseText(HWND hwndDlg, LPSTR p) { wchar_t* q = nullptr; switch (*(WORD*)p) { case 0xFFFE: //BE 大端 大端与小端之间完全颠倒 每个字节之间完全的进行反转 翻转以后就说小端的代码 ConvertBig(p); case 0xFEFF: //LE 小端 SetDlgItemText(hwndDlg, IDC_TEXT, (LPCTSTR)p+2); delete[] q; return; case 0xBBEF: //UTF8 BOM if (p[2] == (char)0xBF) { q = UTF8ToUnicode(p + 3); SetDlgItemText(hwndDlg, IDC_TEXT, q); delete[] q; return; } return; } if (CheckUtf8(p)) { q = UTF8ToUnicode(p); SetDlgItemText(hwndDlg, IDC_TEXT, q); delete[] q; } else { q = ANSIToUnicode(p); SetDlgItemText(hwndDlg, IDC_TEXT, q); delete[] q; } } int GetFileSize(FILE* pf) { long m = ftell(pf); fseek(pf, 0, SEEK_END); long n = ftell(pf); fseek(pf, m, SEEK_SET); return n; } void ReadTextFile(HWND hwndDlg, LPCTSTR sFile) { FILE* pf = _wfopen(sFile, L"rb"); if (!pf) return; int nSize = GetFileSize(pf); if (nSize > 0) { char* p = new char[nSize + 2]; auto n = fread(p, 1, nSize, pf); p[n] = 0; p[n + 1] = 0; ParseText(hwndDlg, p); // SetDlgItemText(hwndDlg, IDC_TEXT, p); delete[] p; } fclose(pf); } void onDropFile(HWND hwndDlg, HDROP hDrop) { TCHAR s[MAX_PATH]; int nCount = DragQueryFile(hDrop, 0, s, _countof(s)); //取第一个文件名 如果要去最后一个,先求出总数再ncount-1 //SetDlgItemText(hwndDlg, IDC_TEXT, s); ReadTextFile(hwndDlg, s); DragFinish(hDrop); } INT_PTR CALLBACK theProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DROPFILES: onDropFile(hwndDlg, (HDROP)wParam); break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, 88); break; } } } return 0; } int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { UINT_PTR n = DialogBox(hInstance, (LPCWSTR)IDD_MAIN_DLG, NULL, theProc); return 0; }
codec.cpp编码格式转换
需要了解utf8编码规则
UTF-8编码规则如下:
如果字符的Unicode码值范围是U+0000至U+007F(即0~127),则使用一个字节表示,最高位为0。
如果字符的Unicode码值范围是U+0080至U+07FF(即128~2047),则使用两个字节表示,最高位为110,第二高位为10。
如果字符的Unicode码值范围是U+0800至U+FFFF(即2048~65535),则使用三个字节表示,最高位为1110,第二高位为10,第三高位为10。
如果字符的Unicode码值范围是U+10000至U+10FFFF(即65536~1114111),则使用四个字节表示,最高位为11110,第二高位为10,第三高位为10,第四高位为10
#include<windows.h> bool CheckUtf8(LPCSTR p) //检查是否为utf8不带bom头格式 { auto q = p; while (*p) { BYTE c = *p; BYTE x = 0x80; int n = 0; while ((c & x) == x) ++n, x >>= 1; if (n == 1 || n > 4) return false; ++p; while (--n>0) { c = *p++; if (c >> 6 != 2) //00000010 把这个数直接左移6位 看他的高位是不是10 return false; } } return true; } void ConvertBig(LPSTR p) { while (*(WORD*)p) //双字节的0结尾结束 { /* CHAR c = *p; *p = p[1]; p[1] = c;*/ *p = *p ^ p[1]; //没有中间变量的 反转 p[1] = *p ^ p[1]; *p = *p ^ p[1]; p += 2; } } char* UnicodeToANSI(const wchar_t* str) { int n = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL); //第一次求长度 带L是Unicode的格式 auto p = new char[n + 1]; n = WideCharToMultiByte(CP_ACP, 0, str, -1, p, n, NULL, NULL); //第二次填充 p, n 你申请的空间,边界限制 p[n] = 0; //结尾 return p; } //算出长度 申请空间 填充长度 wchar_t* ANSIToUnicode(const char* str) { wchar_t n = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); auto p = new wchar_t[n + 1]; MultiByteToWideChar(CP_ACP, 0, str, -1, p, n); return p; } wchar_t* UTF8ToUnicode(const char* str) { int n = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); auto p = new wchar_t[n + 1]; n = MultiByteToWideChar(CP_UTF8, 0, str, -1,p, n); p[n] = 0; return p; } char* UTF8ToANSI(const char* str) { auto p = UTF8ToUnicode(str); auto q= UnicodeToANSI(p); delete[] p; return q; }
针对void ConvertBig(LPSTR p)函数相应释义
1、MFC框架构建:
要使用MFC静态链接库,链接器中要选择 窗口 (/SUBSYSTEM:WINDOWS)
a)必须派生CWinApp类
b)并且重写虚函数InitInstance,作为MFC的框架入口函数。
c)必须在全局区申请一个派生类对象。
2、如何在MFC窗口中接收消息呢?
a)所有MFC的窗口都对应一个系统的派生类,包括:对话框类、控件类,框架和视图等等;
b)消息的接收必须在派生类内,使用消息映射机制实现。
c)消息机制就是MFC内部管理消息循环,在窗口派生类中建立消息与成员函数的关联;
d)MFC类向导第一页是控件编号,选择不同控件对应不同的消息;
e)MFC类向导第二页是主窗口消息,包括WM_MOUSEMOVE,WM_DROPFILES等。
消息映射机制
3、MFC的窗口类库封装:
a)所有的窗口类(包括:对话框类、控件类,框架和视图等等)都由CWnd类同一的窗口基类派生。
b)CWnd类内部有核心成员变量HWND m_hWnd,就如同CSocket类内部有核心成员SOCKET m_hSocket;
c)CWnd类几乎封装所有跟HWND打交道的API,
例如:
void CWnd::SetWindowText(LPCTSTR lpszString)
{
SetWindowText(m_hWnd, lpszString);
}
void CWnd::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint)
{
ASSERT(::IsWindow(m_hWnd) );
MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint);
}
CApp.h
#pragma once
#include<afxwin.h>
#include "CMainDlg.h"
class CApp :public CWinApp
{
BOOL InitInstance()
{
CMainDlg dlg;
dlg.DoModal();
return 0;
}
};
CApp.cpp
#include "CApp.h"
CApp theApp;
CMainDlg.h
#pragma once #include "afxdialogex.h" // CMainDlg 对话框 class CMainDlg : public CDialogEx { DECLARE_DYNAMIC(CMainDlg) public: CMainDlg(CWnd* pParent = nullptr); // 标准构造函数 virtual ~CMainDlg(); // 对话框数据 #ifdef AFX_DESIGN_TIME enum { IDD = IDD_MAIN_DLG }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 DECLARE_MESSAGE_MAP() public: afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnClickedAdd(); };
CMainDlg.cpp
// CMainDlg.cpp: 实现文件 #include "afxdialogex.h" #include "CMainDlg.h" #include "resource.h" // CMainDlg 对话框 IMPLEMENT_DYNAMIC(CMainDlg, CDialogEx) CMainDlg::CMainDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_MAIN_DLG, pParent) { } CMainDlg::~CMainDlg() { } void CMainDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CMainDlg, CDialogEx) //消息映射机制 管理所有消息的连接桥 ON_WM_MOUSEMOVE() ON_WM_LBUTTONDOWN() ON_BN_CLICKED(IDC_ADD, &CMainDlg::OnClickedAdd) END_MESSAGE_MAP() // CMainDlg 消息处理程序 void CMainDlg::OnMouseMove(UINT nFlags, CPoint point) { CString str; str.Format(L"x=%d,y=%d", point.x, point.y); SetWindowText(str); if (MK_LBUTTON &nFlags) { str += "左键按下"; } if (MK_RBUTTON & nFlags) { str += "右键按下"; } if (MK_SHIFT & nFlags) { str += "SHIFT键按下"; } SetWindowText(str); CDialogEx::OnMouseMove(nFlags, point); } void CMainDlg::OnLButtonDown(UINT nFlags, CPoint point) { CString str; str.Format(L"x=%d,y=%d", point.x, point.y); // MessageBox(str, L"点击"); CDialogEx::OnLButtonDown(nFlags, point); } void CMainDlg::OnClickedAdd() { CString str; GetDlgItemText(IDC_LEFT, str); double fLeft=_tstof(str); GetDlgItemText(IDC_RIGHT, str); double fRight = _tstof(str); double fResult = fLeft + fRight; str.Format(L"%g", fResult); SetDlgItemText(IDC_RESULT, str); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。