第303章 テーブルを挿入する


今回は、テーブルを挿入する機能を追加します。

また、メニューの「挿入」「基本項目入力」で背景の色とか 壁紙(?)も指定できるようにします。



「基本項目入力」ダイアログボックスで、背景の色や、壁紙を指定できるようにしました。



テーブルを挿入するには、挿入したい場所にカーソルを移動して メニューの「挿入」「<TABLE></TABLE>」を選択します。

すると左の図のようなダイアログボックスが出るので、必要な項目を 設定します。そうすると何も記入されていないテーブルタグが 挿入されます。この<TD></TD>タグに内容を入れていきます。


ブラウザで見ると、左の図のような感じになります。



では、プログラムを見てみましょう。

// htmledit03.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "新規作成(&N)...", IDM_NEW MENUITEM "上書き保存(&S)", IDM_SAVE MENUITEM "名前を付けて保存(&A)...", IDM_SAVEAS MENUITEM SEPARATOR MENUITEM "アプリケーションの終了(&X)", IDM_END END POPUP "挿入(&I)" BEGIN MENUITEM "基本項目入力(&B)...", IDM_BASICINPUT MENUITEM SEPARATOR MENUITEM "<P>", IDM_P MENUITEM "<BR>", IDM_BR MENUITEM "<H*></H*>...", IDM_H MENUITEM "<IMG>...", IDM_IMAGE MENUITEM "<A HREF></A>...", IDM_A MENUITEM "<TABLE></TABLE>...", IDM_TABLE END POPUP "ブラウザ(&B)" BEGIN MENUITEM "ブラウザ起動(&E)", IDM_BROWSER END END ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYBASICINPUT DIALOG DISCARDABLE 0, 0, 187, 121 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "基本項目入力" FONT 9, "MS Pゴシック" BEGIN EDITTEXT IDC_EDIT1,39,7,141,14,ES_AUTOHSCROLL EDITTEXT IDC_EDIT2,39,27,141,14,ES_AUTOHSCROLL EDITTEXT IDC_EDIT3,39,47,141,14,ES_AUTOHSCROLL DEFPUSHBUTTON "OK",IDOK,39,100,50,14 PUSHBUTTON "キャンセル",IDCANCEL,96,100,50,14 LTEXT "タイトル",IDC_STATIC,7,7,23,8 LTEXT "作者",IDC_STATIC,7,30,15,8 LTEXT "E-Mail",IDC_STATIC,7,47,20,8 CONTROL "色",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,35,76,23,10 CONTROL "壁紙",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,67,76,32, 10 GROUPBOX "背景",IDC_STATIC,26,67,133,26 CONTROL "指定しない",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,108, 76,46,10 END MYHTAG DIALOG DISCARDABLE 0, 0, 187, 93 STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "見出しタグの挿入" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,40,72,50,14 PUSHBUTTON "キャンセル",IDCANCEL,95,72,50,14 COMBOBOX IDC_COMBO1,51,7,18,68,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP LTEXT "大きさ",IDC_STATIC,7,7,32,11 LTEXT "コンテンツ",IDC_STATIC,7,27,39,10 EDITTEXT IDC_EDIT1,51,27,129,32,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN END MYIMGTAG DIALOG DISCARDABLE 0, 0, 187, 91 STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "イメージの挿入" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,43,70,41,14 PUSHBUTTON "キャンセル",IDCANCEL,101,70,41,14 CONTROL "パス付き",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,42,15 EDITTEXT IDC_EDIT1,50,7,107,16,ES_AUTOHSCROLL LTEXT "ファイル名",IDC_STATIC,7,33,38,11 EDITTEXT IDC_EDIT2,50,29,107,16,ES_AUTOHSCROLL PUSHBUTTON "参照",IDC_BUTTON1,160,31,20,15 CONTROL "画像を確認する",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,52,61,15 END MYTABLETAG DIALOG DISCARDABLE 0, 0, 95, 133 STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "テーブルの挿入" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,7,112,33,14 PUSHBUTTON "キャンセル",IDCANCEL,46,112,33,14 LTEXT "行",IDC_STATIC,7,7,11,10 COMBOBOX IDC_COMBO1,29,7,23,58,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP LTEXT "列",IDC_STATIC,7,27,11,10 COMBOBOX IDC_COMBO2,29,25,23,55,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP CONTROL "BORDER",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,49,41,12 EDITTEXT IDC_EDIT1,51,48,34,14,ES_AUTOHSCROLL CONTROL "CAPTION",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,67,44,12 COMBOBOX IDC_COMBO3,51,67,34,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP EDITTEXT IDC_EDIT2,17,89,71,14,ES_AUTOHSCROLL END

メニューと、ダイアログボックスのリソース・スクリプトです。

メニューに<A>タグと<TABLE>タグが増えました

MYBASICINPUTダイアログボックスに背景を選択する項目が増えました。

MYTABLETAGダイアログボックスが増えました。

// htmedit03.cpp #ifndef STRICT #define STRICT #endif #define ID_EDIT 100 #define ID_EDIT2 101 #define MY_BUF_SIZE 1024 * 64 - 1 #include <windows.h> #include <windowsx.h> #include "resource.h" typedef struct _tagHData { char szTagNo[4]; char szContents[256]; } MYHTAG, *LPMYHTAG; typedef struct _tagImgData { char szFileName[MAX_PATH]; char szPath[MAX_PATH]; BOOL bPath; } MYIMGTAG, *LPMYIMGTAG; typedef struct _tagTableData { char szRow[8]; char szColumn[8]; char szTitle[64]; char szTitleAlign[16]; char szBorder[8]; BOOL bTitle; BOOL bBorder; } MYTABLETAG, *LPMYTABLETAG; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyBasicInputProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyHProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyImgProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyAProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyTableProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); BOOL MySetHTML(HWND); int MyBasicInput(HWND); BOOL MySaveAs(HWND); BOOL MySave(HWND); BOOL MyInsertTag(HWND, HWND, char *); BOOL MyInsertH(HWND, HWND); BOOL MyInsertIMG(HWND, HWND); BOOL MyGetFileTitle(HWND, HWND, BOOL); BOOL MyGetBodyColor(HWND); BOOL MyGetWallPaper(HWND); BOOL MyInsertA(HWND, HWND); BOOL MyGetHREFFile(HWND, HWND, BOOL); BOOL MyInsertTable(HWND, HWND); char szClassName[] = "htmedit03"; //ウィンドウクラス char *lpszWinTitleOrg = "猫でもわかるHTMLエディタ[%s]"; char *lpszHead = "<HTML>\r\n<HEAD>\r\n<TITLE>"; char szTitle[64] = "タイトル"; char *lpszBody1 = "</TITLE>\r\n</HEAD>\r\n<BODY"; char szBody2[256]; char *lpszBody3 =">\r\n"; char *lpszAddress = "<ADDRESS>"; char *lpszMailto = "<A HREF=\"mailto:"; char szEMail[256] = "webmaster@kumei.ne.jp"; char *lpszMailEnd = "\">"; char szName[64] = "Yasutaka Kumei"; char *lpszCloseA = "</A>"; char *lpszEnd = "</ADDRESS>\r\n</BODY>\r\n</HTML>"; char szFileName[MAX_PATH]; char szFileTitle[64];

MYTABLETAG構造体をtypedefが増えました。

その他、新しく加わった関数のプロトタイプ宣言が増えました。また、 文字列を格納するグローバル変数の一部が変更になったり、新たに追加になりました。

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; 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, "猫でもわかるHTMLエディタ", //タイトルバーにこの名前が表示されます 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; }

いつもの通りです。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; static HWND hEdit, hEdit_hide; HINSTANCE hInst; CREATESTRUCT *lpcs; char szWinTitle[64]; switch (msg) { case WM_CREATE: wsprintf(szWinTitle, lpszWinTitleOrg, "無題"); SetWindowText(hWnd, szWinTitle); lpcs = (CREATESTRUCT *)lp; hInst = lpcs->hInstance; hEdit = CreateWindow("EDIT", "", WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_HSCROLL | WS_VSCROLL, 0, 0, 0, 0, hWnd, (HMENU)ID_EDIT, hInst, NULL); hEdit_hide = CreateWindow("EDIT", "", WS_CHILD, 0, 0, 0, 0, hEdit, (HMENU)ID_EDIT2, hInst, NULL); SetFocus(hEdit); break; case WM_SIZE: MoveWindow(hEdit, 0, 0, LOWORD(lp), HIWORD(lp), TRUE); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_BASICINPUT: if (MyBasicInput(hEdit) == IDCANCEL) break; id = MessageBox(hWnd, "現在のソースファイルが置き換わりますがよろしいですか", "注意", MB_YESNO | MB_ICONQUESTION); if (id == IDNO) break; MySetHTML(hEdit); SetFocus(hEdit); break; case IDM_SAVEAS: MySaveAs(hEdit); wsprintf(szWinTitle, lpszWinTitleOrg, szFileTitle); SetWindowText(hWnd, szWinTitle); break; case IDM_NEW: if (SendMessage(hEdit, EM_GETMODIFY, 0, 0)) { id = MessageBox(hWnd, "変更を保存しますか", "注意", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) MySave(hEdit); } SetWindowText(hEdit, ""); strcpy(szFileName, ""); strcpy(szFileTitle, ""); wsprintf(szWinTitle, lpszWinTitleOrg, "無題"); SetWindowText(hWnd, szWinTitle); break; case IDM_SAVE: id = MessageBox(hWnd, "上書きしてもよろしいですか", "上書き保存", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { MySave(hEdit); wsprintf(szWinTitle, lpszWinTitleOrg, szFileTitle); SetWindowText(hWnd, szWinTitle); } break; case IDM_P: MyInsertTag(hEdit, hEdit_hide, "<P>"); break; case IDM_BR: MyInsertTag(hEdit, hEdit_hide, "<BR>"); break; case IDM_H: MyInsertH(hEdit, hEdit_hide); break; case IDM_IMAGE: MyInsertIMG(hEdit, hEdit_hide); break; case IDM_BROWSER: if (strcmp(szFileName, "") == 0) { MessageBox(hWnd, "まだHTMLファイルが保存されていません", "Error", MB_OK); break; } ShellExecute(hWnd, "open", szFileName, NULL, NULL, SW_SHOWNORMAL); break; case IDM_A: MyInsertA(hEdit, hEdit_hide); break; case IDM_TABLE: MyInsertTable(hEdit, hEdit_hide); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { if (SendMessage(hEdit, EM_GETMODIFY, 0, 0)) { id = MessageBox(hWnd, "変更を保存しますか", "保存", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) MySave(hEdit); } DestroyWindow(hEdit_hide); DestroyWindow(hEdit); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

メインウィンドウのプロシージャですが、メニューからIDM_Aが選択されたらMyInsertA関数を IDM_TABLEが選択されたらMyInsertTable関数を呼びます。

BOOL MySetHTML(HWND hEdit) { char szBuf[1024*10]; strcpy(szBuf, lpszHead); strcat(szBuf, szTitle); strcat(szBuf, lpszBody1); strcat(szBuf, szBody2); strcat(szBuf, lpszBody3); strcat(szBuf, lpszAddress); strcat(szBuf, lpszMailto); strcat(szBuf, szEMail); strcat(szBuf, lpszMailEnd); strcat(szBuf, szName); strcat(szBuf, lpszCloseA); strcat(szBuf, lpszEnd); SetWindowText(hEdit, szBuf); SendMessage(hEdit, EM_SETMODIFY, (WPARAM)TRUE, 0); return TRUE; }

この関数も少し変更になっています。グローバル変数のszBody2やlpszBody3が 増えたためです。

int MyBasicInput(HWND hEdit) { HINSTANCE hInst; int id; hInst = (HINSTANCE)GetWindowLong(hEdit, GWL_HINSTANCE); id = DialogBox(hInst, "MYBASICINPUT", hEdit, (DLGPROC)MyBasicInputProc); return id; }

この関数に変更はありません。

LRESULT CALLBACK MyBasicInputProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hTitle, hName, hEMail, hWallPaper, hColor, hNotSpecify; static int nBack; //0:nothing 1:Color 2:WallPaper switch (msg) { case WM_INITDIALOG: strcpy(szBody2, ""); hTitle = GetDlgItem(hDlg, IDC_EDIT1); hName = GetDlgItem(hDlg, IDC_EDIT2); hEMail = GetDlgItem(hDlg, IDC_EDIT3); hWallPaper = GetDlgItem(hDlg, IDC_RADIO2); hColor = GetDlgItem(hDlg, IDC_RADIO1); hNotSpecify = GetDlgItem(hDlg, IDC_RADIO3); SetWindowText(hTitle, szTitle); SetWindowText(hName, szName); SetWindowText(hEMail, szEMail); SetFocus(hTitle); switch (nBack) { case 0: Button_SetCheck(hNotSpecify, BST_CHECKED); break; case 1: Button_SetCheck(hColor, BST_CHECKED); break; case 2: Button_SetCheck(hWallPaper, BST_CHECKED); break; default: MessageBox(hDlg, "内部エラーです", "Error", MB_OK); break; } return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: Edit_GetText(hTitle, szTitle, sizeof(szTitle)); Edit_GetText(hName, szName, sizeof(szName)); Edit_GetText(hEMail, szEMail, sizeof(szEMail)); if (Button_GetCheck(hColor) == BST_CHECKED) { if (!MyGetBodyColor(hDlg)) break; nBack = 1; } if (Button_GetCheck(hWallPaper) == BST_CHECKED) { if (!MyGetWallPaper(hDlg)) break; nBack = 2; } if (Button_GetCheck(hNotSpecify) == BST_CHECKED) { nBack = 0; } EndDialog(hDlg, IDOK); return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; } return FALSE; } return FALSE; }

MYBASICINPUTダイアログボックスのプロシージャです。

WM_INITDIALOGメッセージが来たら、szBody2を空にしておきます。 これを忘れると、最初に背景色を設定して、次回設定しなかった場合 前回の色が使われてしまうという不具合が起こります。 nBackの値に従って、ラジオボタンの選択をしておきます。2度目に ダイアログが呼ばれた場合、前回の設定が表示されます。

OKボタンが押されたら、nBackの値に従って、背景色を設定したり 背景の画像選択をしたりする関数を呼びます。

BOOL MySaveAs(HWND hEdit) { OPENFILENAME ofn; HANDLE hFile; char szBuf[MY_BUF_SIZE]; DWORD dwWritten; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hEdit; ofn.lpstrFilter = "htmlファイル\0*.htm;*.html\0All Files(*.*)\0*.*\0\0"; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = sizeof(szFileTitle); ofn.lpstrDefExt = "html"; ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; if (GetSaveFileName(&ofn)) { hFile = CreateFile(szFileName, GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { MessageBox(hEdit, "ファイルのオープンに失敗しました", "Error", MB_OK); return FALSE; } Edit_GetText(hEdit, szBuf, MY_BUF_SIZE); WriteFile(hFile, szBuf, strlen(szBuf), &dwWritten, NULL); SetEndOfFile(hFile); CloseHandle(hFile); SendMessage(hEdit, EM_SETMODIFY, (WPARAM)FALSE, 0); } return TRUE; } BOOL MySave(HWND hEdit) { HANDLE hFile; char szBuf[MY_BUF_SIZE]; DWORD dwWritten; if (strcmp(szFileName, "") == 0) { MessageBox(hEdit, "まず名前を付けて保存してください。", "確認", MB_OK); MySaveAs(hEdit); return TRUE; } Edit_GetText(hEdit, szBuf, MY_BUF_SIZE); hFile = CreateFile(szFileName, GENERIC_WRITE, 0, 0, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { MessageBox(hEdit, "ファイルをオープンできません", "Error", MB_OK); return FALSE; } WriteFile(hFile, szBuf, strlen(szBuf), &dwWritten, NULL); if (strlen(szBuf) != dwWritten) { MessageBox(hEdit, "書き込みに失敗しました", "Error", MB_OK); CloseHandle(hFile); return FALSE; } CloseHandle(hFile); SendMessage(hEdit, EM_SETMODIFY, (WPARAM)FALSE, 0); return TRUE; } BOOL MyInsertTag(HWND hEdit1, HWND hEdit2, char *lpszTag) { SetWindowText(hEdit2, lpszTag); SendMessage(hEdit2, EM_SETSEL, (WPARAM)0, (LPARAM)-1); SendMessage(hEdit2, WM_COPY, 0, 0); SendMessage(hEdit1, WM_PASTE, 0, 0); return TRUE; } BOOL MyInsertH(HWND hEdit, HWND hEdit_hide) { HINSTANCE hInst; MYHTAG myh; char szBuf[512]; hInst = (HINSTANCE)GetWindowLong(hEdit, GWL_HINSTANCE); if (DialogBoxParam(hInst, "MYHTAG", hEdit, (DLGPROC)MyHProc, (LPARAM)&myh) == IDCANCEL) return FALSE; strcpy(szBuf, "<H"); strcat(szBuf, myh.szTagNo); strcat(szBuf, ">"); strcat(szBuf, myh.szContents); strcat(szBuf, "</H"); strcat(szBuf, myh.szTagNo); strcat(szBuf, ">"); MyInsertTag(hEdit, hEdit_hide, szBuf); return TRUE; } LRESULT CALLBACK MyHProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hCombo, hEditContents; static LPMYHTAG lpmyh; switch (msg) { case WM_INITDIALOG: lpmyh = (LPMYHTAG)lp; hCombo = GetDlgItem(hDlg, IDC_COMBO1); hEditContents = GetDlgItem(hDlg, IDC_EDIT1); ComboBox_AddString(hCombo, "1"); ComboBox_AddString(hCombo, "2"); ComboBox_AddString(hCombo, "3"); ComboBox_AddString(hCombo, "4"); ComboBox_AddString(hCombo, "5"); ComboBox_AddString(hCombo, "6"); return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: ComboBox_GetText(hCombo, lpmyh->szTagNo, sizeof(lpmyh->szTagNo)); Edit_GetText(hEditContents, lpmyh->szContents, sizeof(lpmyh->szContents)); EndDialog(hDlg, IDOK); return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; } return FALSE; } return FALSE; } BOOL MyInsertIMG(HWND hEdit, HWND hEdit_hide) { HINSTANCE hInst; MYIMGTAG myimg; char szBuf[1024]; hInst = (HINSTANCE)GetWindowLong(hEdit, GWL_HINSTANCE); if (DialogBoxParam(hInst, "MYIMGTAG", hEdit, (DLGPROC)MyImgProc, (LPARAM)&myimg) == IDCANCEL) return FALSE; strcpy(szBuf, "<IMG SRC=\""); if (myimg.bPath) strcat(szBuf, myimg.szPath); strcat(szBuf, myimg.szFileName); strcat(szBuf, "\">"); MyInsertTag(hEdit, hEdit_hide, szBuf); return TRUE; } LRESULT CALLBACK MyImgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hButton, hPath, hFile, hCheck, hImg; static LPMYIMGTAG lpimg; static BOOL bImg, bPath; switch (msg) { case WM_INITDIALOG: lpimg = (LPMYIMGTAG)lp; hButton = GetDlgItem(hDlg, IDC_BUTTON1); hCheck = GetDlgItem(hDlg, IDC_CHECK1); hPath = GetDlgItem(hDlg, IDC_EDIT1); hFile = GetDlgItem(hDlg, IDC_EDIT2); hImg = GetDlgItem(hDlg, IDC_CHECK2); if (bImg) Button_SetCheck(hImg, BST_CHECKED); else Button_SetCheck(hImg, BST_UNCHECKED); if (bPath) { EnableWindow(hPath, TRUE); Button_SetCheck(hCheck, BST_CHECKED); } else { EnableWindow(hPath, FALSE); Button_SetCheck(hCheck, BST_UNCHECKED); } return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: Edit_GetText(hFile, lpimg->szFileName, MAX_PATH); if (Button_GetCheck(hCheck) == BST_CHECKED) { Edit_GetText(hPath, lpimg->szPath, MAX_PATH); lpimg->bPath = TRUE; } else { strcpy(lpimg->szPath, ""); lpimg->bPath = FALSE; } EndDialog(hDlg, IDOK); return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; case IDC_CHECK1: if (Button_GetCheck(hCheck) == BST_CHECKED) { EnableWindow(hPath, TRUE); bPath = TRUE; } else { EnableWindow(hPath, FALSE); bPath = FALSE; } return TRUE; case IDC_BUTTON1: MyGetFileTitle(hDlg, hFile, bImg); return TRUE; case IDC_CHECK2: if (Button_GetCheck(hImg) == BST_CHECKED) bImg = TRUE; else bImg = FALSE; return TRUE; } return FALSE; } return FALSE; } BOOL MyGetFileTitle(HWND hDlg, HWND hFile, BOOL bImg) { OPENFILENAME ofn; char szFileTitle[MAX_PATH], szFileName[MAX_PATH]; szFileTitle[0] = '\0'; szFileName[0] = '\0'; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFilter = "gifファイル\0*.gif\0jpegファイル\0*.jpg;*.jpeg\0すべてのファイル\0*.*\0\0"; ofn.Flags = OFN_HIDEREADONLY; if (!GetOpenFileName(&ofn)) return FALSE; SetWindowText(hFile, szFileTitle); if (bImg) { if (ShellExecute(hDlg, "open", szFileName, NULL, NULL, SW_SHOWNORMAL) <= (HINSTANCE)32) { MessageBox(hDlg, "画像を表示できません", "Error", MB_OK); return FALSE; } } return TRUE; }

これらの関数に変更はありません。

BOOL MyGetBodyColor(HWND hDlg) { CHOOSECOLOR cc; static COLORREF crResult = RGB(0, 0, 0); static DWORD dwCustColor[16]; char szRed[8], szGreen[8], szBlue[8]; memset(&cc, 0, sizeof(CHOOSECOLOR)); cc.lStructSize = sizeof(CHOOSECOLOR); cc.hwndOwner = hDlg; cc.rgbResult = crResult; cc.Flags = CC_RGBINIT; cc.lpCustColors = dwCustColor; if (!ChooseColor(&cc)) return FALSE; crResult = cc.rgbResult; wsprintf(szRed, "%02X", GetRValue(crResult)); wsprintf(szGreen, "%02X", GetGValue(crResult)); wsprintf(szBlue, "%02X", GetBValue(crResult)); strcpy(szBody2, " BGCOLOR=\"#"); strcat(szBody2, szRed); strcat(szBody2, szGreen); strcat(szBody2, szBlue); strcat(szBody2, "\""); return TRUE; }

背景の色を表す文字列を作ります。

ChooseColor関数で選択した色は変数crResultに格納されますが、これを単純に 16進で表してもだめです。まず、各色の成分を取得してこれを16進で表し、 文字列に付け加えていきます。これには、マクロを使うと便利です。 (GetRValue, GetGValue, GetBValue)

BOOL MyGetWallPaper(HWND hDlg) { HINSTANCE hInst; MYIMGTAG myimg; hInst = (HINSTANCE)GetWindowLong(hDlg, GWL_HINSTANCE); if (DialogBoxParam(hInst, "MYIMGTAG", hDlg, (DLGPROC)MyImgProc, (LPARAM)&myimg) == IDCANCEL) return FALSE; strcpy(szBody2, " BACKGROUND=\""); if (myimg.bPath) strcat(szBody2, myimg.szPath); strcat(szBody2, myimg.szFileName); strcat(szBody2, "\""); return TRUE; }

背景となる壁紙を取得して、BODYタグの文字列を作る関数です。

ダイアログボックスとそのプロシージャはMYIMGTAGのそれをそのまま使っています。

BOOL MyInsertA(HWND hEdit, HWND hEdit_hide) { HINSTANCE hInst; MYIMGTAG myatag; char szBuf[1024]; hInst = (HINSTANCE)GetWindowLong(hEdit, GWL_HINSTANCE); if (DialogBoxParam(hInst, "MYIMGTAG", hEdit, (DLGPROC)MyAProc, (LPARAM)&myatag) == IDCANCEL) return FALSE; strcpy(szBuf, ""); MyInsertTag(hEdit, hEdit_hide, szBuf); return TRUE; }

これは、<A>タグを作る関数ですが、ダイアログはMYIMGTAGのそれをそのまま使い、 プロシージャは別に作っています。通常このタグではジャンプ先のHTMLファイルを指定するので プロシージャまで同じにしては都合が悪いからです。

LRESULT CALLBACK MyAProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hPath, hFile, hCheck1, hCheck2; static LPMYIMGTAG lpatag; static BOOL bPath, bKakunin; switch (msg) { case WM_INITDIALOG: lpatag = (LPMYIMGTAG)lp; hPath = GetDlgItem(hDlg, IDC_EDIT1); hFile = GetDlgItem(hDlg, IDC_EDIT2); hCheck1 = GetDlgItem(hDlg, IDC_CHECK1); hCheck2 = GetDlgItem(hDlg, IDC_CHECK2); SetWindowText(hDlg, "A HREFの挿入"); SetWindowText(hCheck2, "ファイルの確認"); if (bKakunin) Button_SetCheck(hCheck2, BST_CHECKED); else Button_SetCheck(hCheck2, BST_UNCHECKED); if (bPath) { EnableWindow(hPath, TRUE); Button_SetCheck(hCheck1, BST_CHECKED); } else { EnableWindow(hPath, FALSE); Button_SetCheck(hCheck1, BST_UNCHECKED); } return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: Edit_GetText(hFile, lpatag->szFileName, MAX_PATH); if (bPath) { Edit_GetText(hPath, lpatag->szPath, MAX_PATH); lpatag->bPath = TRUE; } else { strcpy(lpatag->szPath, ""); lpatag->bPath = FALSE; } EndDialog(hDlg, IDOK); return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; case IDC_CHECK1: if (Button_GetCheck(hCheck1) == BST_CHECKED) { EnableWindow(hPath, TRUE); bPath = TRUE; } else { EnableWindow(hPath, FALSE); bPath = FALSE; } return TRUE; case IDC_CHECK2: if (Button_GetCheck(hCheck2) == BST_CHECKED) bKakunin = TRUE; else bKakunin = FALSE; return TRUE; case IDC_BUTTON1: MyGetHREFFile(hDlg, hFile, bKakunin); return TRUE; } return FALSE; } return FALSE; }

WM_INITDIALOGメッセージが来たら、ダイアログボックスのタイトル名などを一部変更して、 <A>タグ挿入のためのダイアログボックスらしくしています。あとの部分はMYIMGTAG ダイアログボックスのプロシージャとほとんど同じです。

BOOL MyGetHREFFile(HWND hDlg, HWND hFile, BOOL bKakunin) { OPENFILENAME ofn; char szFileTitle[MAX_PATH], szFileName[MAX_PATH]; szFileTitle[0] = '\0'; szFileName[0] = '\0'; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFilter = "HTMLファイル\0*.htm;*.html\0すべてのファイル\0*.*\0\0"; ofn.Flags = OFN_HIDEREADONLY; if (!GetOpenFileName(&ofn)) return FALSE; SetWindowText(hFile, szFileTitle); if (bKakunin) { if (ShellExecute(hDlg, "edit", szFileName, NULL, NULL, SW_SHOWNORMAL) <= (HINSTANCE)32) { MessageBox(hDlg, "ファイルを表示できません", "Error", MB_OK); return FALSE; } } return TRUE; }

ダイアログで「参照」ボタンが押されたときに呼ばれます。

bKakuninがTRUEであれば、選択したファイルを"edit"で開きます。

BOOL MyInsertTable(HWND hEdit, HWND hEdit_hide) { HINSTANCE hInst; MYTABLETAG mytable; char szBuf[1024 * 2]; int i, j, nRow, nCol; hInst = (HINSTANCE)GetWindowLong(hEdit, GWL_HINSTANCE); if (DialogBoxParam(hInst, "MYTABLETAG", hEdit, (DLGPROC)MyTableProc, (LPARAM)&mytable) == IDCANCEL) return FALSE; nRow = atoi(mytable.szRow); nCol = atoi(mytable.szColumn); strcpy(szBuf, "\r\n"); if (mytable.bTitle) { strcat(szBuf, ""); strcat(szBuf, mytable.szTitle); strcat(szBuf, "\r\n"); } for (j = 1; j <= nRow; j++) { for (i = 1; i <= nCol; i++) { strcat(szBuf, ""); } if (j != nRow) strcat(szBuf, "\r\n"); } strcat(szBuf, "\r\n"); MyInsertTag(hEdit, hEdit_hide, szBuf); return TRUE; }

今回の目玉(??)となるテーブルタグの挿入関数です。

ダイアログボックスが戻ってきたら、nRow, nColに行、列を代入しておきます。

列の分だけ<TD></TD>を書き込み1列の最後には<TR>を付け加えます。 これを行の分だけ繰り返します。しかし、一番最後には<TR>を付け加えません。

面倒そうですが、たいしたものではないですね。

LRESULT CALLBACK MyTableProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hRow, hCol, hBorderCheck, hBorderEdit, hCapCheck, hCapCombo, hCapEdit; static LPMYTABLETAG lpmytable; char szNum[][4] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}; int i; static BOOL bBorder, bCaption; switch (msg) { case WM_INITDIALOG: lpmytable = (LPMYTABLETAG)lp; hRow = GetDlgItem(hDlg, IDC_COMBO1); hCol = GetDlgItem(hDlg, IDC_COMBO2); hBorderCheck = GetDlgItem(hDlg, IDC_CHECK1); hCapCheck = GetDlgItem(hDlg, IDC_CHECK2); hBorderEdit = GetDlgItem(hDlg, IDC_EDIT1); hCapCombo = GetDlgItem(hDlg, IDC_COMBO3); hCapEdit = GetDlgItem(hDlg, IDC_EDIT2); for (i = 0; i < 10; i++) { ComboBox_AddString(hRow, szNum[i]); ComboBox_AddString(hCol, szNum[i]); } ComboBox_SetText(hRow, "1"); ComboBox_SetText(hCol, "1"); ComboBox_AddString(hCapCombo, "top"); ComboBox_AddString(hCapCombo, "bottom"); if (bBorder) { Button_SetCheck(hBorderCheck, BST_CHECKED); ShowWindow(hBorderEdit, SW_SHOW); } else { Button_SetCheck(hBorderCheck, BST_UNCHECKED); ShowWindow(hBorderEdit, SW_HIDE); } if (bCaption) { Button_SetCheck(hCapCheck, BST_CHECKED); ShowWindow(hCapCombo, SW_SHOW); ShowWindow(hCapEdit, SW_SHOW); } else { Button_SetCheck(hCapCheck, BST_UNCHECKED); ShowWindow(hCapCombo, SW_HIDE); ShowWindow(hCapEdit, SW_HIDE); } return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: ComboBox_GetText(hRow, lpmytable->szRow, sizeof(lpmytable->szRow)); ComboBox_GetText(hCol, lpmytable->szColumn, sizeof(lpmytable->szColumn)); if (bBorder) { Edit_GetText(hBorderEdit, lpmytable->szBorder, sizeof(lpmytable->szBorder)); lpmytable->bBorder = TRUE; } else { strcpy(lpmytable->szBorder, ""); lpmytable->bBorder = FALSE; } if (bCaption) { ComboBox_GetText(hCapCombo, lpmytable->szTitleAlign, sizeof(lpmytable->szTitleAlign)); Edit_GetText(hCapEdit, lpmytable->szTitle, sizeof(lpmytable->szTitle)); lpmytable->bTitle = TRUE; } else { strcpy(lpmytable->szTitle, ""); strcpy(lpmytable->szTitleAlign, ""); lpmytable->bTitle = FALSE; } EndDialog(hDlg, IDOK); return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; case IDC_CHECK1: if (Button_GetCheck(hBorderCheck) == BST_CHECKED) { ShowWindow(hBorderEdit, SW_SHOW); bBorder = TRUE; } else { ShowWindow(hBorderEdit, SW_HIDE); bBorder = FALSE; } return TRUE; case IDC_CHECK2: if (Button_GetCheck(hCapCheck) == BST_CHECKED) { ShowWindow(hCapCombo, SW_SHOW); ShowWindow(hCapEdit, SW_SHOW); bCaption = TRUE; } else { ShowWindow(hCapCombo, SW_HIDE); ShowWindow(hCapEdit, SW_HIDE); bCaption = FALSE; } return TRUE; } return FALSE; } return FALSE; }

MYTABLETAGダイアログボックスのプロシージャです。

WM_INITDIALOGメッセージが来たら、コントロール類のウィンドウハンドルを 取得して、staticな変数に格納しておきます。

また、コンボボックスに文字列を追加しておきます。

bBorderがTRUEであれば、BORDERアトリビュートの数字を 記入するエディットコントロールを可視にしておきます。

bCaptionについても同様です。

OKボタンが押されたら、MYTABLE構造体に取得したデータを格納します。 これで、呼び出し元にデータがわたります。こんな面倒なことが いやな場合は、グローバル変数を使ってください。

IDC_CHECK1がチェックされたらBORDERの値を入力するエディットコントロール を可視にします。

IDC_CHECK2がチェックされたら、テーブルのキャプション関連のコントロールを 可視にします。

さて、今回までのプログラムで結構複雑なHTMLが作れるようになりました。 しかし、まだまだ基本的なタグで必須なものが抜けています。いろいろ改良を試みてください。


[SDK第4部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 18/Feb/2001 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。