S-JISからJISに変換するには、
を使います。使い方は_mbcjistojmsと同じです。 (前章を参照してください)#include <mbstring.h> unsigned int _mbcjmstojis( unsigned int c );
を使います。cが2バイト文字の1バイト目であれば 0以外をそうでなければ0を返します。int _ismbblead( unsigned int c );
JIS(日本語メール)では2パイト文字(列)とASCII文字(列)の前に特別な合図がありました。 しかし、S-JISではそのようなものはありません。 そこで、この合図を付けてやる必要があります。 また、「\r\n」は「\n」に変換してやる必要があります。
では、プログラムを見てみましょう。
普通のリソース・スクリプトです。// conv02.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "JISを開く(&O)...", IDM_OPEN MENUITEM "JISで保存(&S)...", IDM_SAVE MENUITEM SEPARATOR MENUITEM "終了(&X)...", IDM_END END END
MySave, MySJisToJis関数のプロトタイプ宣言が増えました。// conv02.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <windowsx.h> #include <mbstring.h> #include "resource.h" #define ID_EDIT 100 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); int MyOpen(HWND, char *, HWND); void MyJisToSJis(char *, char *); int MySave(HWND, char *, HWND); void MySJisToJis(char *, char *); char szClassName[] = "conv02"; //ウィンドウクラス HINSTANCE hInst;
いつもと同じです。int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; hInst = hCurInst; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); }
ウィンドウタイトルが少しだけ変わりました。//ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるJIS<->SJIS変換", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }
szFileNameはstatic変数にしておくとMyOpen関数で開いたファイル名が MySave関数でセーブするときのデフォルトファイル名となります。 (上書き保存するとき便利)//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; static HWND hEdit; RECT rc; static char szFileName[MAX_PATH]=""; switch (msg) { case WM_CREATE: hEdit = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_MULTILINE, 0, 0, 0, 0, hWnd, (HMENU)ID_EDIT, hInst, NULL); break; case WM_SIZE: GetClientRect(hWnd, &rc); MoveWindow(hEdit, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_OPEN: MyOpen(hWnd, szFileName, hEdit); break; case IDM_SAVE: MySave(hWnd, szFileName, hEdit); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hEdit); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }
メニューからIDM_SAVEが選択されるとMySave関数を呼び出します。
szTitle_orgがちょっとだけ変更になりました。int MyOpen(HWND hWnd, char *szFileName, HWND hEdit) { DWORD dwSize; OPENFILENAME ofn; HANDLE hFile; DWORD dwAccBytes = 0; char szTitle[64], *szTitle_org = "猫でもわかるJIS<->SJIS変換[%s]"; char *lpszStr, *lpszResult; char szFile[MAX_PATH]; //オープンするJIS文書 HANDLE hStr, hResult; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = "text(*.txt)\0*.txt\0All files(*.*)\0*.*\0\0"; ofn.lpstrFile = szFileName; ofn.lpstrFileTitle = szFile; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt = "txt"; ofn.lpstrTitle = "JISファイルを開く"; if(GetOpenFileName(&ofn) == 0) return -1; hFile = CreateFile(szFileName, GENERIC_READ, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); dwSize = GetFileSize(hFile, NULL); if (dwSize >= 1024 * 64) { MessageBox(hWnd, "ファイルサイズが大きすぎます", "Too Big File!", MB_OK); CloseHandle(hFile); dwSize = 0; return -1; } //最後にヌル文字を付け加えるのでファイルサイズより1バイト多く確保 hStr = GlobalAlloc(GHND, dwSize + 1); if (hStr == NULL) { MessageBox(hWnd, "メモリ確保に失敗しました", "Error", MB_OK); return -2; } lpszStr = (char *)GlobalLock(hStr); //変換後の文字列を格納するメモリは少し余分に確保しておくと安全 hResult = GlobalAlloc(GHND, dwSize + 1024); if (hResult == NULL) { MessageBox(hWnd, "メモリ確保に失敗しました", "Error", MB_OK); return -2; } lpszResult = (char *)GlobalLock(hResult); ReadFile(hFile, lpszStr, dwSize, &dwAccBytes, NULL); lpszStr[dwAccBytes] = '\0'; MyJisToSJis(lpszStr, lpszResult); Edit_SetText(hEdit, lpszResult); GlobalUnlock(hStr); GlobalUnlock(hResult); GlobalFree(hStr); GlobalFree(hResult); wsprintf(szTitle, szTitle_org, szFile); SetWindowText(hWnd, szTitle); CloseHandle(hFile); return 0; }
この関数に変更はありません。void MyJisToSJis(char *lpOrg, char *lpDest) { int i = 0, iR = 0, c; BOOL bSTART = FALSE;//JIS->SJIS変換が必要かどうか while (1) { if (lpOrg[i] == 0x1b && lpOrg[i + 1] == 0x24 && lpOrg[i + 2] == 0x42) { bSTART = TRUE; i += 3; continue; } if (lpOrg[i] == 0x1b && lpOrg[i+ 1] == 0x28 && lpOrg[i + 2] == 0x42) { bSTART = FALSE; i += 3; continue; } if (lpOrg[i] >= 0x21 && lpOrg[i] <= 0x7e && bSTART) { c = MAKEWORD(lpOrg[i + 1], lpOrg[i]); lpDest[iR] = (char)HIBYTE(_mbcjistojms(c)); lpDest[iR + 1] = (char)LOBYTE(_mbcjistojms(c)); i += 2; iR += 2; continue; } if (i == 0 && lpOrg[0] == '\n') { lpDest[iR] = '\r'; lpDest[iR + 1] = '\n'; i++; iR += 2; continue; } if (lpOrg[i] == '\n' && lpOrg[i - 1] != '\r') { lpDest[iR] = '\r'; lpDest[iR + 1] = '\n'; i++; iR += 2; continue; } if (lpOrg[i] == '\0') { lpDest[iR] = lpOrg[i]; break; } lpDest[iR] = lpOrg[i]; iR++; i++; } return; }
エディットコントロールから文字列を取得するときうっかりint MySave(HWND hWnd, char *szFileName, HWND hEdit) { char *lpszStr, *lpszResult; char szTitle[64], *szTitle_org = "猫でもわかるJIS<->SJIS変換[%s]"; char szFile[MAX_PATH] = ""; OPENFILENAME ofn; HANDLE hFile, hStr, hResult; DWORD dwByte = 0; int iLength; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = "Text files(*.txt)\0*.txt\0All files(*.*)\0*.*\0\0"; ofn.lpstrFile = szFileName; ofn.lpstrFileTitle = szFile; ofn.nMaxFileTitle = MAX_PATH; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; ofn.lpstrDefExt = "txt"; if (!GetSaveFileName(&ofn)) { return -1; } iLength = Edit_GetTextLength(hEdit); if ( iLength >= 1024 * 64) { MessageBox(hWnd, "テキストが大きすぎます", "Error", MB_OK); return -2; } hStr = GlobalAlloc(GHND, iLength + 1); if (hStr == NULL) { MessageBox(hWnd, "メモリ確保に失敗しました", "Error", MB_OK); return -3; } hResult = GlobalAlloc(GHND, iLength + 1024); if (hResult == NULL) { MessageBox(hWnd, "メモリ確保に失敗しました", "Error", MB_OK); return -3; } lpszStr = (char *)GlobalLock(hStr); lpszResult = (char *)GlobalLock(hResult); Edit_GetText(hEdit, lpszStr, iLength + 1); MySJisToJis(lpszStr, lpszResult); hFile = CreateFile(szFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); WriteFile(hFile, lpszResult, strlen(lpszResult), &dwByte, NULL); CloseHandle(hFile); GlobalUnlock(hStr); GlobalUnlock(hResult); GlobalFree(hStr); GlobalFree(hResult); wsprintf(szTitle, szTitle_org, szFile); SetWindowText(hWnd, szTitle); return 0; }
Edit_GetText(hEdit, lpszStr, sizeof(lpszStr));
などとしないでください。
前章と逆のことをする関数です。void MySJisToJis(char *lpszOrg, char *lpszDest) { int i = 0, iR = 0, c; BOOL bSTART = FALSE; while (1) { if (_ismbblead(lpszOrg[i]) && bSTART == FALSE) { lpszDest[iR] = 0x1b; lpszDest[iR + 1] = 0x24; lpszDest[iR + 2] = 0x42; c = MAKEWORD(lpszOrg[i + 1], lpszOrg[i]); lpszDest[iR + 3] = (char)HIBYTE(_mbcjmstojis(c)); lpszDest[iR + 4] = (char)LOBYTE(_mbcjmstojis(c)); bSTART = TRUE; i += 2; iR += 5; if (!_ismbblead(lpszOrg[i])) { lpszDest[iR] = 0x1b; lpszDest[iR + 1] = 0x28; lpszDest[iR + 2] = 0x42; bSTART = FALSE; iR += 3; } continue; } if (_ismbblead(lpszOrg[i]) && bSTART) { c = MAKEWORD(lpszOrg[i + 1], lpszOrg[i]); lpszDest[iR] = (char)HIBYTE(_mbcjmstojis(c)); lpszDest[iR + 1] = (char)LOBYTE(_mbcjmstojis(c)); i += 2; iR += 2; if (!_ismbblead(lpszOrg[i])) { lpszDest[iR] = 0x1b; lpszDest[iR + 1] = 0x28; lpszDest[iR + 2] = 0x42; bSTART = FALSE; iR += 3; } continue; } if (lpszOrg[i] == '\r') { lpszDest[iR] = '\n'; i += 2; iR++; continue; } if (lpszOrg[i] == '\0') { lpszDest[iR] = lpszOrg[i]; break; } lpszDest[iR] = lpszOrg[i]; iR++; i++; } return; }
もっと効率のよい方法で書き換えてみてください。
Update 04/Oct/1999 By Y.Kumei