(1)関数テンプレートを利用してint/std::string型の配列をvectorに設定する
(2)vector(動的配列)を昇順でソートして返す
(3)std::coutで結果を出力する
<動作検証&開発環境>
Visual Studio Community 2019
Version16.1.1
<イメージ>
<使い方>
Windowsデスクトップウィザードでプロジェクトを作成する
コンソールアプリケーション(.exe)を指定する
ソースを追加する
(1)ファイルピッカーで画像ファイルを選択します
(2)シートに画像ファイルのハイパーリンクを設定します
(3)シートの画像ファイルのサムネイルを設定します
<実行イメージ>
<動作検証>
Microsoft Office 365 バージョン1905(11629.20214)
<使い方>
適当なところにソースを貼り付けてください
画像をシートに並べて表示する() を実行します
'/********************************************************
'/* 画像をシートに並べてハイパーリンクを設定する
'/* 1.画像ファイル(.jpg)を選択する(複数選択可)
'/* 2.画像ファイルのサムネイルをシートに並べる
'/* 3.画像ファイルへのハイパーリンクをシートに設定する
'/********************************************************
Public Sub 画像をシートに並べて表示する()
On Error GoTo ErrorOccurred
Dim gazoFiles() As String
Dim iret As Integer, i As Integer
Dim stcol As Integer, strow As Integer
Dim filename As String
'//ファイル選択ダイアログで画像ファイルを選択する
With Application.FileDialog(msoFileDialogFilePicker)
'選択可能ファイル(.jpg)設定
.Filters.Add "画像ファイル(Jpeg)", "*.jpg"
'複数ファイル選択可能
.AllowMultiSelect = True
'ファイルピッカー表示
If .Show = False Then
Exit Sub
Else
'SelectedItemsはインデックス1から開始するのでFor文で実装する際は注意
i = 0
For Each tmpstr In .SelectedItems
ReDim Preserve gazoFiles(i)
gazoFiles(i) = tmpstr
i = i + 1
Next
End If
End With
'//シートを初期化していいか確認メッセージを表示する
iret = MsgBox(ActiveSheet.Name & " : シートを初期化してもよろしいですか?", _
vbYesNo + vbQuestion, "画像をシートに並べて表示する")
If iret = vbNo Then Exit Sub
'//シートを初期化する
シートクリア ActiveSheet.Name
'//画像のサムネイルとハイパーリンクを設定
i = 1
stcol = 2
strow = 2
For Each tmpstr In gazoFiles
'ハイパーリンクを設定
'詳細はOfficeデベロッパーセンター参照
filename = Mid(tmpstr, InStrRev(tmpstr, "¥") + 1)
Range(Cells(strow, stcol), Cells(strow, stcol)).Select
ActiveSheet.Hyperlinks.Add _
Anchor:=ActiveSheet.Range(Cells(strow, stcol), Cells(strow, stcol)), _
Address:=tmpstr, _
ScreenTip:=tmpstr, _
TextToDisplay:=filename
'サムネイル画像を設定
Range(Cells(strow + 1, stcol), Cells(strow + 1, stcol)).Select
ActiveSheet.Pictures.Insert(tmpstr).Select
Selection.ShapeRange.Height = 150
'次の開始位置を算出(横方向は最大4画像とする)
If (i Mod 4) = 0 Then
stcol = 2
strow = strow + 12
Else
stcol = stcol + 13
End If
'次の画像はi番目
i = i + 1
Next
Range("A1").Select
Exit Sub
ErrorOccurred:
MsgBox "何かエラーが発生しました", vbCritical
End Sub
'/********************************************************
'/ シートをクリアする
'/ stname:クリア対象シート名
'/********************************************************
Private Sub シートクリア(ByVal stname As String)
Dim sp As Variant
'//シート選択
ThisWorkbook.Sheets(stname).Activate
'//セルを初期化する
Cells.Select
Selection.UnMerge
Selection.Clear
Selection.ColumnWidth = 3
Selection.RowHeight = 17
Selection.Font.Name = "Meiryo UI"
Selection.Font.Size = 12
Selection.Borders.LineStyle = False
'//中央揃えを設定
Selection.HorizontalAlignment = xlLeft
Selection.VerticalAlignment = xlCenter
'//セルの折り返しを解除
Selection.WrapText = False
'//オートシェイプを削除する
For Each sp In ActiveSheet.Shapes
sp.Delete
Next
ActiveWindow.Zoom = 80
Range("A1").Select
End Sub
よろしければポチッと押してください
]]>
(1)エディットボックスに入力された2進数文字列を10進数文字列に変換する
(2)エディットボックスに入力された10進数文字列を2進数文字列に変換する
<動作検証&開発環境>
Visual Studio Community 2017
Version15.9.7
<イメージ>
<使い方>
(1)MFCアプリケーションでプロジェクトを作成
(2)アプリケーションの種類に ダイアログベース を指定
(3)ダイアログにUIを配置する
(4)エディットボックスにメンバ変数を追加する
※UpdateDataでアクセスするため
(5)ラベルにメンバ変数を追加する
※UpdateDataでアクセスするため
(6)ソースを追加する
MFCApplication1Dlg.h
class CMFCApplication1Dlg : public CDialogEx
{
//~~省略~~
public:
afx_msg void OnBnClickedButton1();
CString m_Edit1;
CButton *cb;
CString m_Label1;
};
MFCApplication1Dlg.cpp
//プロトタイプ宣言
CString ConvertBinary2Decimal(CString moji);
CString ConvertDecimal2Binary(CString moji);
CMFCApplication1Dlg::CMFCApplication1Dlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_MFCAPPLICATION1_DIALOG, pParent)
, m_Edit1(_T(""))
, m_Label1(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMFCApplication1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_Edit1);
DDX_Text(pDX, IDC_Label1, m_Label1);
}
BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CMFCApplication1Dlg::OnBnClickedButton1)
END_MESSAGE_MAP()
BOOL CMFCApplication1Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
//〜〜省略〜〜
//ラジオボタンの初期値を設定
cb = (CButton*)GetDlgItem(IDC_RADIO1);
cb->SetCheck(TRUE);
return TRUE;
}
/******************************************************
ボタンクリックイベントハンドラ
ラジオボタンの選択により処理を分岐する
2進数を10進数に変換:ConvertBinary2Decimal
10進数を2進数に変換:ConvertDecimal2Binary
******************************************************/
void CMFCApplication1Dlg::OnBnClickedButton1()
{
CString cs,csRet;
//エディットボックスの内容をメンバ変数にセット
UpdateData(TRUE);
if (m_Edit1.GetLength() == 0) return;
//入力文字列チェック&変換
if (cb->GetCheck())
{
//入力値チェック
if (m_Edit1 != m_Edit1.SpanIncluding(L"01"))
{
AfxMessageBox(L"2進数は0か1を入力してください", MB_ICONERROR);
return;
}
else
{
//上限桁数はunsigned intのマックス値まで
if (m_Edit1.GetLength() > 32)
{
AfxMessageBox(L"入力2進数は32桁がマックス値です", MB_ICONERROR);
return;
}
}
//2進数から10進数に変換
m_Label1 = ConvertBinary2Decimal(m_Edit1);
UpdateData(FALSE);
}
else
{
//入力値チェック
if (m_Edit1 != m_Edit1.SpanIncluding(L"0123456789"))
{
AfxMessageBox(L"10進数は0-9の数値を入力してください", MB_ICONERROR);
return;
}
else
{
//上限桁数はunsigned intのマックス値まで
if (m_Edit1.GetLength() > 10)
{
AfxMessageBox(L"入力10進数は10桁がマックス値です", MB_ICONERROR);
return;
}
else if (m_Edit1.GetLength() == 10)
{
if (m_Edit1 > L"4294967295")
{
AfxMessageBox(L"入力10進数はunsigned intの上限がマックス値です", MB_ICONERROR);
return;
}
}
}
//10進数から2進数に変換
m_Label1 = ConvertDecimal2Binary(m_Edit1);
UpdateData(FALSE);
}
}
/******************************************************
2進数文字列を10進数文字列に変換する
符号なし/unsigned intのマックス値まで変換可能
引 数:2進数文字列
戻り値:10進数文字列
******************************************************/
CString ConvertBinary2Decimal(CString moji)
{
CString csRet(L""),cwk;
unsigned int uiRet = 0;
for (int i = 0; i < moji.GetLength(); i++)
{
cwk = moji.Mid(i, 1);
if (cwk == L"1")
{
uiRet += (unsigned int)pow(2, (moji.GetLength() - 1) - i);
}
}
csRet.Format(L"%u",uiRet);
return csRet;
}
/******************************************************
10進数文字列を2進数文字列に変換する
符号なし/unsigned intのマックス値まで変換可能
引 数:10進数文字列
戻り値:2進数文字列
******************************************************/
CString ConvertDecimal2Binary(CString moji)
{
CString csRet(L""), cwk;
wchar_t wt[20];
ZeroMemory(&wt, sizeof(wchar_t) * 20);
wsprintf(wt,L"%s", moji);
unsigned int idecimal = 0,ui;
//_ttoiによる数値変換だとintの最大値に丸められるため独自に計算する
//idecimal = _ttoi(moji)
for (int i = 0; i < moji.GetLength(); i++)
{
cwk = moji.Mid(i, 1);
ui = _ttoi(cwk);
idecimal += ((unsigned int)pow(10, (moji.GetLength() - 1) - i) * ui);
}
unsigned int syo, amari;
for(;;)
{
syo = idecimal / 2;
amari = idecimal % 2;
cwk.Format(L"%u",amari);
csRet = (cwk + csRet);
//商が0になったら終了
if (syo == 0) break;
idecimal = syo;
}
return csRet;
}
よろしければポチッと押してください
(1)FileSystemObjectのGetFileメソッドでファイル情報を取得する
(2)Openステートメントでバイナリファイルの指定位置から指定サイズだけ切り出す
<イメージ>
ファイル情報を出力します
バイナリファイルの指定位置から指定サイズ分取得して別ファイルに切り出します
※サンプルでは50000バイト目から10000バイト分を切り出します
<動作検証&開発環境>
Microsoft Office 2016
<使い方>
(1)参照設定を行います
[Alt]+[F11]でVBE(VBAエディター)を表示します
メニューの[ツール(T)]から[参照設定(R)]を選択します
Microsoft Scripting Runtimeをチェックして[OK]を押下してください
(2)標準モジュールを追加します
(3)ソースを貼り付けます
'********************************************
'ファイル情報を表示する
'GetFileの詳細はDeveloperNetwork参照
'********************************************
Public Sub ファイル情報を表示する()
On Error GoTo lblerror
Dim filename As String
Dim myfso As FileSystemObject, myinfo As Object
Dim sret As String
'//テストファイルパス
filename = ThisWorkbook.Path + "¥testpicture.jpg"
'//FSOオブジェクトを取得する
Set myfso = CreateObject("Scripting.FileSystemObject")
'//ファイル情報を取得する
Set myinfo = myfso.GetFile(filename)
sret = "【File】" + vbCrLf
'//パス
sret = sret + myinfo.Path + vbCrLf
'//ファイル名
sret = sret + myinfo.Name + vbCrLf
'//ファイルサイズ
sret = sret + CStr(myinfo.size) + "バイト" + vbCrLf
'//ファイルタイプ
sret = sret + myinfo.Type + vbCrLf
'//ファイル作成日時・最終アクセス日時・最終更新日時
sret = sret + "作成日時 :" + DateFormat(myinfo.DateCreated) + vbCrLf
sret = sret + "最終アクセス日時:" + DateFormat(myinfo.DateLastAccessed) + vbCrLf
sret = sret + "最終更新日時 :" + DateFormat(myinfo.DateLastModified) + vbCrLf
'//フォルダ作成日時・最終アクセス日時・最終更新日時
sret = sret + "【Folder】" + vbCrLf
sret = sret + "作成日時 :" + DateFormat(myinfo.ParentFolder.DateCreated) + vbCrLf
sret = sret + "最終アクセス日時:" + DateFormat(myinfo.ParentFolder.DateLastAccessed) + vbCrLf
sret = sret + "最終更新日時 :" + DateFormat(myinfo.ParentFolder.DateLastModified) + vbCrLf
MsgBox sret, vbInformation
lblerror:
Set myinfo = Nothing
Set myfso = Nothing
End Sub
'********************************************
'Date型の書式を設定する
'********************************************
Private Function DateFormat(ByVal dt As Date) As String
DateFormat = Format(dt, "yyyy-mm-dd hh:nn:ss")
End Function
'********************************************
'指定位置から指定サイズ切り出して保存する
'********************************************
Public Sub バイナリファイルから指定サイズ切り出す()
On Error GoTo lblerror
Dim readfile As String, writefile As String
Dim rfl As Long, lidx As Long, wfl As Long
'//切り出す開始位置とサイズ
'//アドレス0xC350(50000)から10000バイト切り出す
Dim myichi As Long
myichi = 0
Dim mysize As Long
mysize = 2910731
'//ファイル指定
readfile = ThisWorkbook.Path + "¥testpicture.jpg"
writefile = ThisWorkbook.Path + "¥testbinary.bin"
'//バッファ
Dim rbuf() As Byte
Dim wbuf() As Byte
'//ファイルを開く
rfl = FreeFile
Open readfile For Binary Access Read As rfl
'//書き込みファイルが存在する場合は中身をいったんクリアする
wfl = FreeFile
If Dir(writefile) <> "" Then
Open writefile For Output As wfl
Close (wfl)
End If
Open writefile For Binary Access Write As wfl
'//読み込み
ReDim rbuf(LOF(rfl))
Get rfl, , rbuf
'//書き込み
ReDim wbuf(mysize)
For lidx = 0 To LOF(rfl) - 1
If lidx < myichi Then GoTo nextbyte
If lidx > (myichi + mysize - 1) Then Exit For
Put wfl, , rbuf(lidx)
nextbyte:
Next
Close rfl
Close wfl
Exit Sub
lblerror:
MsgBox "何かエラーが発生しました", vbCritical
End Sub
よろしければポチッと押してください
]]>(1)RegOpenKeyExでレジストリをオープンします
HKEY_LOCAL_MACHINE
SOFTWARE¥Microsoft¥Windows NT¥CurrentVersion
(2)RegQueryValueExを使ってレジストリの値を取得します
ProductName
ReleaseId
CurrentBuildNumber
UBR
(3)Windows10のバージョン情報を表示します
<動作検証&開発環境>
Visual Studio Community 2017
<イメージ>
OS Windows 10 Enterprise
バージョン 1803
OSビルド 17134.345
<使い方>
(1)プロジェクトの選択でデスクトップウィザードを指定します
アプリケーションの種類:コンソールアプリケーション
共通ヘッダの追加:MFCにチェック
(2)コードを記述します
//プロトタイプ宣言
CString GetWindows10Version();
CString GetRegDataText(DWORD dwType, DWORD dwSize, TCHAR *buf, CString csEntry);
const int DMAX_SIZE = 256;
int main()
{
if (hModule != nullptr)
{
// MFC を初期化して、エラーの場合は結果を印刷します。
if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
{
//〜〜省略〜〜
}
else
{
//Window10のバージョン情報をレジストリから取得
CString csRet = GetWindows10Version();
//結果を出力
AfxMessageBox(csRet, MB_ICONINFORMATION);
}
}
else
{
//〜〜省略〜〜
}
return nRetCode;
}
/******************************************************
GetWindows10Version
レジストリからRegQueryValueExを使用してバージョン情報を取得する
戻り値
バージョン情報(タイプ/サイズ/値)
******************************************************/
CString GetWindows10Version()
{
HKEY hKey = nullptr; //レジストリキーのハンドル
LONG lRet;
CString csRet=_T("");
TCHAR buf[DMAX_SIZE];
DWORD dwSize,dwType,dwVal=0;
//レジストリオープン
lRet = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
_T("SOFTWARE¥¥Microsoft¥¥Windows NT¥¥CurrentVersion"),
0,
KEY_QUERY_VALUE,
&hKey
);
//レジストリオープンエラー
if (lRet != ERROR_SUCCESS)
{
csRet = _T("RegOpenKeyExエラー");
goto lbl_Error;
}
//RegQueryValueExについてはDeveloperNetwork参照
//// プロダクト(OS)を取得 //////////
dwSize = DMAX_SIZE;
ZeroMemory(&buf, DMAX_SIZE*2);
lRet = RegQueryValueEx(
hKey,
_T("ProductName"),
0,
&dwType,
(LPBYTE)buf,
&dwSize
);
//プロダクト 値取得エラー
if (lRet != ERROR_SUCCESS)
{
csRet = _T("RegQueryValueEx(ProductName)エラー");
goto lbl_Error;
}
csRet = _T("【Windows Version情報】¥r¥n");
csRet += GetRegDataText(dwType, dwSize, buf, _T("ProductName"));
//// リリースIDを取得 //////////
dwSize = DMAX_SIZE;
ZeroMemory(&buf, DMAX_SIZE * 2);
lRet = RegQueryValueEx(
hKey,
_T("ReleaseId"),
0,
&dwType,
(LPBYTE)buf,
&dwSize
);
//リリースID 値取得エラー
if (lRet != ERROR_SUCCESS)
{
csRet = _T("RegQueryValueEx(ReleaseId)エラー");
goto lbl_Error;
}
csRet += GetRegDataText(dwType, dwSize, buf,_T("ReleaseId"));
//// ビルドバージョンを取得 //////////
dwSize = DMAX_SIZE;
ZeroMemory(&buf, DMAX_SIZE * 2);
lRet = RegQueryValueEx(
hKey,
_T("CurrentBuildNumber"),
0,
&dwType,
(LPBYTE)buf,
&dwSize
);
//ビルドバージョン 値取得エラー
if (lRet != ERROR_SUCCESS)
{
csRet = _T("RegQueryValueEx(CurrentBuildNumber)エラー");
goto lbl_Error;
}
csRet += GetRegDataText(dwType, dwSize, buf, _T("CurrentBuildNumber"));
//// ビルドバージョン(UBR)を取得 //////////
dwSize = DMAX_SIZE;
ZeroMemory(&buf, DMAX_SIZE * 2);
lRet = RegQueryValueEx(
hKey,
_T("UBR"),
0,
&dwType,
(LPBYTE)buf,
&dwSize
);
//ビルドバージョン(UBR) 値取得エラー
if (lRet != ERROR_SUCCESS)
{
csRet = _T("RegQueryValueEx(UBR)エラー");
goto lbl_Error;
}
csRet += GetRegDataText(dwType, dwSize, buf, _T("UBR"));
lbl_Error:
if (hKey != NULL)
{
//レジストリクローズ
RegCloseKey(hKey);
}
return csRet;
}
/******************************************************
GetRegDataText
取得したタイプ(データ型)/サイズ/値より表示用文字列を生成
引数
dwType : タイプ(データ型)
dwSize : データサイズ
buf : レジストリの値
csEntry : レジストリのエントリ名
戻り値
表示用文字列
******************************************************/
CString GetRegDataText(DWORD dwType,DWORD dwSize,TCHAR *buf,CString csEntry)
{
CString csRet = _T("¥r¥n=== ") + csEntry + _T(" ==========¥r¥n");
CString cwk;
int iwk;
//読みだしたタイプに応じてサイズと値を設定
//ここでは必要なタイプのみ設定するがタイプの詳細はDeveloperNetwork参照
switch (dwType)
{
case REG_DWORD:
iwk = (int)buf[0];
cwk.Format(_T(" VALUE: %d¥r¥n SIZE: %d TYPE: REG_DWORD¥r¥n"), iwk, dwSize);
break;
case REG_SZ:
cwk.Format(_T(" VALUE: %s¥r¥n SIZE: %d TYPE: REG_SZ¥r¥n"), buf, dwSize);
break;
}
csRet += cwk;
return csRet;
}
よろしければポチッと押してください
FSO(FileSystemObject)を使ってファイルの読み・書き・追記を行うサンプルです
(1)ファイルにテキストを書き込む
(2)ファイルにテキストを追記する
(3)ファイルからテキストを読み込む
(4)フォルダを作成する
(5)ファイルを別フォルダにリネームしてコピーする
(6)ファイルをワイルドカードを使用して別フォルダにコピーする
(7)ファイルを削除する
<実行イメージ>
上記(1)〜(7)実行後のイメージです
(1)(2) ファイル書き込み・追記を行います
(3) 追記を行ったファイルを読み込み結果をシートに出力します
(4)(5) フォルダを作成し作成したファイルを100回コピーします
(6) 100回コピーされたファイルを別フォルダにワイルドカードを使用してコピーします
(7) コピーしたファイルからファイル末尾に不可した数値が10の倍数のファイルを削除します
<動作検証&開発環境>
Microsoft Office 2016
<使い方>
(1)参照設定を行います
[Alt]+[F11]でVBE(VBAエディター)を表示します
メニューの[ツール(T)]から[参照設定(R)]を選択します
Microsoft Scripting Runtimeをチェックして[OK]を押下してください
これによりForReading / TristateFalseなどの定数が使用できるようになります
(2)標準モジュールを追加してソースを貼り付けます
(3)「FSOでファイルを操作する」 プロシージャを実行します
(1)CreateEllipticRgnで楕円形のリージョン(Crgn)を作成します
(2)CreateRectRgnで四角形のリージョン(CRgn)を作成します
(3)CombineRgnでリージョンを結合します
(4)SetWindowRgnで非矩形ウィンドウを作成します
<動作検証&開発環境>
Visual Studio Community 2017
<イメージ>
元のダイアログ
[楕円1個]ボタン押下により楕円形のウィンドウに切り替え
[楕円2個]ボタン押下により楕円形2個のウィンドウに切り替え
[楕円くり抜き]ボタン押下により左右の矩形と楕円をXORしたウィンドウに切り替え
CombineRgnされた矩形ダイアログと楕円ダイアログのXOR部分が透明になります
<使い方>
(1)MFCアプリケーションでプロジェクトを作成
(2)アプリケーションの種類でダイアログベースを選択
(3)生成されたクラスで基底クラスにCDialogを選択
(4)MFCApplication1.rcを下記の通り修正
※MFCApplication1は各環境のプロジェクト名
(5)クラスウィザードでWM_NCHITTESTメッセージを追加
※非矩形ウィンドウはタイトルバーがなくなるためタイトルバー以外でドラッグ移動できるようにする
(6)ボタンを追加します(ダイアログの中央に集めてください)
(7)ソースを追加します
よろしければポチッと押してください
(1)ファイル選択ダイアログでファイルを指定します
(2)指定ファイルのCFile::GetStatusでファイルステータスを取得します
CTime | m_ctime | ファイルの作成日時 |
CTime | m_mtime | ファイルの最終更新日時 |
CTime | m_atime | ファイルが読み取りで最後にアクセスされた日時 |
ULONGLONG | m_size | ファイルの論理サイズ |
BYTE | m_attribute | ファイル属性 |
char | m_szFullName | ファイルパス |
(3)ファイル属性(m_attribute)を取得します
(4)ファイルステータスの取得結果をメッセージボックスで表示します
<動作検証&開発環境>
Visual Studio Community 2017
<イメージ>
<使い方>
(1)"Windowsデスクトップウィザード" を選択します
(2)コンソールアプリケーション(.exe)を選択します
(3)MFCにチェックを入れます
(4)コードを記述します
よろしければポチッと押してください
]]>
(1)VBAで3D迷路(プチゲーム)を作ってみる 後編 です
前回は3Dマップ表示まで行いました
(前回 オートシェイプで3D迷路を作ってみる(前編) )
今回はコマンドボタン(前、左、右)によって移動できます
感動のエンディング www もご覧ください
(2)マップ表示はオートシェイプを使用します
(3)全体マップと3D表示マップを実装しました
全体マップ:20×20の全体マップです(スタートとゴールに●を表示します)
3Dマップ:縦8階層×横9ブロックの3D表示の元データです
(4)3Dマップは常にユーザの正面目線で描画しています
全体マップで北向きのとき:ユーザの現在位置の上側を描画
全体マップで東向きのとき:ユーザの現在位置の右側を描画
全体マップで南向きのとき:ユーザの現在位置の下側を描画
全体マップで西向きのとき:ユーザの現在位置の左側を描画
(5)コマンドボタンは「前進む」「左向く」「右向く」を実装しました
(6)3D表示エリアは64セル×64セルです
正面(後方)の壁の四角形、横壁の台形表示とセル数との関係は以下の通りです
(7)前回の3Dマップ描画で壁が足りなかった部分を修正しました
四角形と台形の表示処理
1)壁(情報コード=9、99)のときの3D描画
・描画対象外(目に見えない範囲 情報コード=7、8)ならスキップ
・手前の壁(四角形)を描画する
2)通路(情報コード=1、2、0)のときの3D描画
・中央より左(0から3)のとき、左が壁なら左側に台形を描画
・中央より右(5から7)のとき、右が壁なら右側に台形を描画
・中央(4)のとき左が壁なら左側、右が壁なら右側、両方なら両方に台形を描画
3)通路のとき前のブロックが壁なら前面に四角形を描画
<実行イメージ>
YouTubeに動画アップしましたのでご覧ください
<動作検証>
Microsoft Office 2016
<使い方>
適当なところにソースを貼り付けてください
シート初期化() を実行すると3D迷路を描画します
※アクティブセルの情報を全てクリアしますのでご注意ください
ソースは3Dマップ描画部のみ掲載します
下記URLで完全版を公開しております
http://sagami-ss.sub.jp/pg-sample/src/Excel_3DMaze_SourceCode.txt
(1)VBAで3D迷路(プチゲーム)を作ってみます
今回は3Dを表示するところまでです
サンプルマップを5種類切り替えて表示します
次回、マップ上を移動できるようにするつもりです(お盆には完成させたい)
(2)3D迷路に必要な台形描画はオートシェイプを使用します
(3)3D迷路の仕様
(3)-1.マップの大きさは64×64セルとします
(3)-2.正面の壁、横の壁はオートシェイプを使用します
(3)-3.奥行きは8階層(インデックス0から7とし0が最奥、7が手前です)
・最奥は壁9ブロック、手前は壁1ブロック
・座標が通路でとなりが壁の時に横壁を表示します(台形を描画)
・横壁は中央より左の時は右辺が短い台形、中央より右の時は左辺が短い台形
(3)-4.描画は奥から順番に行います(結果として見えない壁も描画処理します)
(3)-5.階層別の壁と台形の表示位置は下図の通りです
・上の図の赤色分部が台形(横の壁)を描画するときの台形の幅
・下図の灰色分部がマップ表示されない部分(見えない部分)
<実行イメージ>
シート初期化()実行直後
下の画像を見るとまだまだ横の壁の表示処理が足りない、、、汗
次回、修正します
[次のサンプルマップ]押下によりサンプルが切り替わります
<動作検証>
Microsoft Office 2016
<使い方>
適当なところにソースを貼り付けてください
シート初期化() を実行すると3D迷路を描画します
※アクティブセルの情報を全てクリアしますのでご注意ください
]]>
(1)MFCのSDIアプリケーションにマウスイベントを追加します
WM_MOUSELEAVE : ウィンドウのクライアント領域を離れた
WM_MOUSEMOVE : マウスカーソルが動いた
WM_RBUTTONDOWN : マウスの右ボタンが押下された
WM_RBUTTONUP : マウスの右ボタンが解放された
(2)マウスの右ボタンでクライアント領域をドラッグすると四角形を描画します
CDC->Rectangle
(3)メニューで描画する四角形の塗りつぶし色、線の種類を変更できます
塗りつぶし色
・赤系の色
・緑系の色
・青系の色
線のスタイル
・実線(PS_SOLID)
・破線(PS_DASH)
・点線(PS_DOT)
<実行イメージ>
メニューを指定すると描画する四角形の色と線のスタイルが変更できます
マウスの右ボタン押下するとスタート位置セット、
マウスの右ボタンUPすると終了位置をセットして四角形を描画します
<動作検証&開発環境>
Visual Studio Community 2017
<使い方>
1.MFCアプリケーションでプロジェクトを作成
2.アプリケーションの種類でシングルドキュメントを選択
※その他の設定は下図参照
3.ユーザーインターフェイス機能でクラシックメニューを使用するを選択
※その他の設定は下図参照
4.高度な機能で不要なチェックを外す
5.プロジェクト構成を確認してソースを追加する
6.クラスウィザードでCChileViewクラスにマウスイベントハンドラを追加
WM_MOUSELEAVE : クライアント領域の外にカーソルが移動したとき座標を初期化
WM_MOUSEMOVE : 移動中のマウスカーソルを変更する
WM_RBUTTONDOWN : マウスの右ボタンでスタート座標取得
WM_RBUTTONUP : マウスの右ボタンUPで終了座標取得して描画
7.リソースの[Menu]->[IDR_MAINFRAME]を修正してメニュー項目を追加
以下項目を追加します
赤系の色 : ID_32771
緑系の色 : ID_32772
青系の色 : ID_32773
――境界線をセット――
実線 : ID_32774
破線 : ID_32775
点線 : ID_32776
※塗りつぶし色と線のスタイルはCheckMenuRadioItemでそれぞれグループ化します
メニューのIDはここではID_32771~ID32776ですがソース内もそれぞれの環境に応じて変更してください
8.クラスウィザードでCMainFrameにOnCommandを追加します
メニューが操作されたとき塗りつぶし色、線のスタイルを変更する
MFCApplication1.h
class CMFCApplication1App : public CWinApp
{
//〜〜省略〜〜
//グローバル変数
public:
//メニューでの選択値
COLORREF selClr;
COLORREF selLinfClr;
int iSelStyle;
};
extern CMFCApplication1App theApp;
MainFrm.h
class CMainFrame : public CFrameWnd
{
//〜〜省略〜〜
private:
//塗りつぶしの色
COLORREF clr[3] = {
RGB(216,130,187),
RGB(146,208,80),
RGB(155,194,230)
};
//線の色
COLORREF lineclr[3] = {
RGB(199,73,157),
RGB(97,148,40),
RGB(47,117,181)
};
//線のスタイル
int iStyle[3] = {
PS_SOLID,
PS_DASH,
PS_DOT
};
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
};
MainFrm.cpp
#include "stdafx.h"
#include "MFCApplication1.h"
#include "MainFrm.h"
//CMainFrameオブジェクト
extern CMFCApplication1App theApp;
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//〜〜省略〜〜
CMenu *pMenu = this->GetMenu();
//ON_COMMAND ハンドラーが自動的に無効になるのを停止
CFrameWnd::m_bAutoMenuEnable = FALSE;
//全てのメニューを有効化
pMenu->EnableMenuItem(ID_32771, MF_BYCOMMAND | MF_ENABLED);
pMenu->EnableMenuItem(ID_32772, MF_BYCOMMAND | MF_ENABLED);
pMenu->EnableMenuItem(ID_32773, MF_BYCOMMAND | MF_ENABLED);
pMenu->EnableMenuItem(ID_32774, MF_BYCOMMAND | MF_ENABLED);
pMenu->EnableMenuItem(ID_32775, MF_BYCOMMAND | MF_ENABLED);
pMenu->EnableMenuItem(ID_32776, MF_BYCOMMAND | MF_ENABLED);
//色のメニューをグループ化して赤系にチェックOn
//CheckMenuRadioItemについてはDeveloperNetwork参照
pMenu->CheckMenuRadioItem(ID_32771, ID_32773, ID_32771, MF_BYCOMMAND);
//線のメニューをグループ化して実線にチェックOn
pMenu->CheckMenuRadioItem(ID_32774, ID_32776, ID_32774, MF_BYCOMMAND);
//初期値をセット
theApp.selClr = clr[0];
theApp.selLinfClr = lineclr[0];
theApp.iSelStyle = iStyle[0];
return 0;
}
/***********************************************************
OnCommand
メニューが変更されたら塗りつぶし色、線の種類を変更
※環境に応じてメニューのIDは変更してください
***********************************************************/
BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
{
int iSelClr = 0;
int iSelStyle = 0;
CMenu *pMenu = this->GetMenu();
//現在(変更前)のメニューの状態を取得
if (pMenu->GetMenuState(ID_32771, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelClr = 0;
if (pMenu->GetMenuState(ID_32772, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelClr = 1;
if (pMenu->GetMenuState(ID_32773, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelClr = 2;
if (pMenu->GetMenuState(ID_32774, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelStyle = 0;
if (pMenu->GetMenuState(ID_32775, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelStyle = 1;
if (pMenu->GetMenuState(ID_32776, MF_BYCOMMAND | MF_CHECKED) & MF_CHECKED) iSelStyle = 2;
//変更されたメニュー項目(iItem)で更新
UINT iItem = LOWORD(wParam);
switch (iItem)
{
case ID_32771:
iSelClr = 0;
break;
case ID_32772:
iSelClr = 1;
break;
case ID_32773:
iSelClr = 2;
break;
case ID_32774:
iSelStyle = 0;
break;
case ID_32775:
iSelStyle = 1;
break;
case ID_32776:
iSelStyle = 2;
break;
default:
;
}
//塗りつぶしグループの値を変更
if (iItem == ID_32771 || iItem == ID_32772 || iItem == ID_32773)
{
pMenu->CheckMenuRadioItem(ID_32771, ID_32773, iItem, MF_BYCOMMAND);
theApp.selClr = clr[iSelClr];
theApp.selLinfClr = lineclr[iSelClr];
}
//線の種類グループの値を変更
if (iItem == ID_32774 || iItem == ID_32775 || iItem == ID_32776)
{
pMenu->CheckMenuRadioItem(ID_32774, ID_32776, iItem, MF_BYCOMMAND);
theApp.iSelStyle = iStyle[iSelStyle];
}
TRACE(L"iSelClr=%d iSelStyle=%d¥r¥n",iSelClr, iSelStyle);
return CFrameWnd::OnCommand(wParam, lParam);
}
ChildView.h
class CChildView : public CWnd
{
//〜〜省略〜〜
public:
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnMouseLeave();
private:
void DrawRectangle();
//描画中フラグ(描画中のときTRUE)
BOOL bDrawing;
//座標情報
CPoint stPoint, edPoint;
};
ChildView.cpp
#include "stdafx.h"
#include "MFCApplication1.h"
#include "ChildView.h"
//CMainFrameオブジェクト
extern CMFCApplication1App theApp;
BEGIN_MESSAGE_MAP(CChildView, CWnd)
//〜〜省略〜〜
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_MOUSELEAVE()
END_MESSAGE_MAP()
/***********************************************************
OnRButtonDown
子ウィンドウでマウスの右ボタンが押下されたイベント
***********************************************************/
void CChildView::OnRButtonDown(UINT nFlags, CPoint point)
{
bDrawing = TRUE;
SetCursor(LoadCursor(NULL,IDC_SIZEALL));
//開始位置を終了位置を初期化
stPoint.SetPoint(0, 0);
edPoint.SetPoint(0, 0);
//開始位置をセット
stPoint = point;
CWnd::OnRButtonDown(nFlags, point);
}
/***********************************************************
OnRButtonUp
子ウィンドウでマウスの右ボタンが離されたイベント
***********************************************************/
void CChildView::OnRButtonUp(UINT nFlags, CPoint point)
{
if (bDrawing)
{
SetCursor(LoadCursor(NULL,IDC_ARROW));
//終了位置をセット
edPoint = point;
//四角形を描画する
DrawRectangle();
}
bDrawing = FALSE;
CWnd::OnRButtonUp(nFlags, point);
}
/***********************************************************
OnMouseMove
マウスが移動中に発生するイベント
***********************************************************/
void CChildView::OnMouseMove(UINT nFlags, CPoint point)
{
if (bDrawing)
{
SetCursor(LoadCursor(NULL,IDC_SIZEALL));
}
//WM_MOUSELEAVEイベントを受け取れるようにしておく
//TrackMouseEventについてはDeveloperNetwork参照
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = WM_NCMOUSELEAVE;
tme.hwndTrack = this->GetSafeHwnd();
tme.dwHoverTime = 0; //関係ないので0をセットしておく
TrackMouseEvent(&tme);
CWnd::OnMouseMove(nFlags, point);
}
/***********************************************************
OnMouseLeave
子ウィンドウのクライアント領域をマウスが離れたイベント
描画フラグとアイコンをリセットする
***********************************************************/
void CChildView::OnMouseLeave()
{
bDrawing = FALSE;
SetCursor(LoadCursor(NULL, IDC_ARROW));
TRACE(L"OnMouseLeave¥r¥n");
CWnd::OnMouseLeave();
}
/***********************************************************
DrawRectangle
開始Pointと終了Pointに対して四角形を描画する
塗りつぶし色、線の色、線のスタイルはメニューの選択値を取得
***********************************************************/
void CChildView::DrawRectangle()
{
CDC *pDC = this->GetDC();
//四角形を塗りつぶすブラシ
CBrush brs(theApp.selClr);
CBrush *pOldBrush = pDC->SelectObject(&brs);
//四角形を描画するペン
//1より大きな幅を指定するとPS_SOLIDスタイルになるため幅は0とする
CPen pen;
pen.CreatePen(theApp.iSelStyle, 0, theApp.selLinfClr);
CPen *pOldPen = pDC->SelectObject(&pen);
//四角形を描画する領域
CRect rect(stPoint,edPoint);
//参考情報として出力ウィンドウに座標表示
CString cs;
cs.Format(L"st.x=%d st.y=%d ed.x=%d ed.y=%d¥r¥n",
stPoint.x, stPoint.y, edPoint.x, edPoint.y);
TRACE(cs);
//四角形を描画
pDC->Rectangle(rect);
//オブジェクトを戻す
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
}
よろしければポチッと押してください
]]>
(1)MFCのSDIアプリケーションにリストコントロール(CListCtrl)を追加する
(2)リストコントロールをCreate(サイズ・WindowStyle指定)する
(3)リストコントロールのフォントを変更してみる(MS UI Gothic使用)
(4)ヘッダ設定(InsertColumn)、データ設定(InsertItem)を行う
(5)イベントを追加する(WindowProc)
・LVN_ITEMCHANGED : リストコントロールに変更があった
・LVN_COLUMNCLICK : リストコントロールのヘッダが左クリックされた
<実行イメージ>
フォントをMS UI Gothicに変更しヘッダ・データをセット
※データは東京都の市区町村別人口
リスト選択により選択行番号と選択行の情報を表示
<動作検証&開発環境>
Visual Studio Community 2017
<使い方>
1.MFCアプリケーションでプロジェクトを作成
2.アプリケーションの種類でシングルドキュメントを選択
3.ユーザーインターフェイス機能でくクラシックメニューを使用するを選択
※その他の設定は下図参照
4.高度な機能で不要なチェックを外す
5.プロジェクト構成を確認しソースを追加する
6.クラスウィザードにてCChileViewクラスにOnCreateハンドラーを追加
※OnCreateでリストコントロールを生成しデータを設定する
7.クラスウィザードにてCChileViewクラスにWindowProcハンドラーを追加
※WindowProcでリストコントロールのイベント処理を行う
MainFrm.cpp
//メインフレームのサイズ設定を行う
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE
| WS_SYSMENU;
//cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
//ウィンドウサイズとクライアント領域を一致させる
cs.dwExStyle = WS_EX_CLIENTEDGE;
cs.lpszClass = AfxRegisterWndClass(0);
//作業領域のサイズを取得
//画面全体からシステムのタスクバーやアプリケーションのツールバーが占有する領域を除いた部分
CRect rcSpara;
SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcSpara, NULL);
//ウィンドウサイズの設定
CRect rect(0, 0, 600, 400);
::AdjustWindowRectEx(&rect, cs.style, TRUE, cs.dwExStyle);
//ウィンドウサイズを取得
cs.cx = rect.Width();
cs.cy = rect.Height();
//画面中央に表示
cs.x = rcSpara.left + (rcSpara.Width() - cs.cx) / 2;
cs.y = rcSpara.top + (rcSpara.Height() - cs.cy) / 2;
return TRUE;
}
ChildView.h
//フォント変更するためCFontオブジェクトを追加
class CChildView : public CWnd
{
//省略~~
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
private:
const int D_IDLISTVIEW = 1000;
void InsertListCtrlItems(CListCtrl *pList);
public:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
CFont *m_pFont;
};
ChildView.cpp
CChildView::CChildView()
{
//子ウィンドにフォントをセット
m_pFont = new CFont;
LOGFONT logFont;
logFont.lfHeight = 12;
logFont.lfWidth = 10;
logFont.lfEscapement = 0;
logFont.lfOrientation = 0;
logFont.lfWeight = FW_DONTCARE;
logFont.lfItalic = FALSE;
logFont.lfUnderline = FALSE;
logFont.lfStrikeOut = FALSE;
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logFont.lfQuality = DEFAULT_QUALITY;
logFont.lfPitchAndFamily = FF_DONTCARE;
lstrcpy(logFont.lfFaceName, L"MS UI Gothic");
m_pFont->CreateFontIndirect(&logFont);
}
CChildView::~CChildView()
{
//フォントオブジェクトを破棄
delete m_pFont;
}
/***********************************************************
OnCreate
SDIで子ウィンドウの作成時にリストコントロール(CListCtrl)を生成
***********************************************************/
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
//ウィンドウサイズを取得
CFrameWnd *pFrm = GetParentFrame();
CRect rect;
pFrm->GetClientRect(&rect);
//リストコントロール(レポート形式)を配置
//ウィンドウサイズに対して余白10で配置する
CListCtrl *pListctrl = new CListCtrl();
//List-View Window Stylesはデベロッパーセンターを参照
pListctrl->Create(
WS_VISIBLE | WS_BORDER | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_REPORT | LVS_SINGLESEL,
CRect(10, 10, rect.Width()-20, rect.Height()-20), this, D_IDLISTVIEW);
//拡張スタイルを設定
pListctrl->SetExtendedStyle(pListctrl->GetExtendedStyle() | LVS_EX_FULLROWSELECT);
//リストカラムセッティング
LV_COLUMN lvclm;
ZeroMemory(&lvclm, sizeof(LV_COLUMN));
lvclm.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
//インデックス0の列はは常にLVCFMT_LEFTとなる
//詳細はデベロッパーセンターのRemarks参照
//lvclm.fmt = LVCFMT_CENTER;
lvclm.iSubItem = 0;
lvclm.pszText = L"地域コード";
lvclm.cx = 130;
pListctrl->InsertColumn(0, &lvclm);
lvclm.fmt = LVCFMT_LEFT;
lvclm.iSubItem = 1;
lvclm.pszText = L"市区町村名";
lvclm.cx = 250;
pListctrl->InsertColumn(1, &lvclm);
lvclm.fmt = LVCFMT_RIGHT;
lvclm.iSubItem = 2;
lvclm.pszText = L"人口(人)";
lvclm.cx = 150;
pListctrl->InsertColumn(2, &lvclm);
//アイテムセット
InsertListCtrlItems(pListctrl);
//フォントをセット
GetDlgItem(D_IDLISTVIEW)->SetFont(m_pFont);
return 0;
}
/***********************************************************
InsertListCtrlItems
リストコントロールにデータ(東京都市区町村の人口)をセット
***********************************************************/
void CChildView::InsertListCtrlItems(CListCtrl *pList)
{
TCHAR twk[64];
int idx=0;
LVITEM lvitm;
struct
{
int id;
TCHAR name[128];
int population;
}item[]={
{ 13101,_T("東京都 千代田区"),61218 },{ 13102,_T("東京都 中央区"),156256 },
{ 13103,_T("東京都 港区"),253018 },{ 13104,_T("東京都 新宿区"),343533 },
{ 13105,_T("東京都 文京区"),227141 },{ 13106,_T("東京都 台東区"),202947 },
{ 13107,_T("東京都 墨田区"),264229 },{ 13108,_T("東京都 江東区"),510574 },
{ 13109,_T("東京都 品川区"),397710 },{ 13110,_T("東京都 目黒区"),283005 },
{ 13111,_T("東京都 大田区"),728423 },{ 13112,_T("東京都 世田谷区"),921720 },
{ 13113,_T("東京都 渋谷区"),229670 },{ 13114,_T("東京都 中野区"),335745 },
{ 13115,_T("東京都 杉並区"),575841 },{ 13116,_T("東京都 豊島区"),298050 },
{ 13117,_T("東京都 北区"),348547 },{ 13118,_T("東京都 荒川区"),216273 },
{ 13119,_T("東京都 板橋区"),574058 },{ 13120,_T("東京都 練馬区"),731696 },
{ 13121,_T("東京都 足立区"),677514 },{ 13122,_T("東京都 葛飾区"),450846 },
{ 13123,_T("東京都 江戸川区"),691084 },{ 13201,_T("東京都 八王子市"),577910 },
{ 13202,_T("東京都 立川市"),179390 },{ 13203,_T("東京都 武蔵野市"),146381 },
{ 13204,_T("東京都 三鷹市"),190432 },{ 13205,_T("東京都 青梅市"),135789 },
{ 13206,_T("東京都 府中市"),261829 },{ 13207,_T("東京都 昭島市"),111902 },
{ 13208,_T("東京都 調布市"),235243 },{ 13209,_T("東京都 町田市"),434091 },
{ 13210,_T("東京都 小金井市"),123813 },{ 13211,_T("東京都 小平市"),192874 },
{ 13212,_T("東京都 日野市"),188327 },{ 13213,_T("東京都 東村山市"),150180 },
{ 13214,_T("東京都 国分寺市"),124501 },{ 13215,_T("東京都 国立市"),74610 },
{ 13218,_T("東京都 福生市"),58210 },{ 13219,_T("東京都 狛江市"),82357 },
{ 13220,_T("東京都 東大和市"),84664 },{ 13221,_T("東京都 清瀬市"),75377 },
{ 13222,_T("東京都 東久留米市"),116360 },{ 13223,_T("東京都 武蔵村山市"),71651 },
{ 13224,_T("東京都 多摩市"),147691 },{ 13225,_T("東京都 稲城市"),90225 },
{ 13227,_T("東京都 羽村市"),55225 },{ 13228,_T("東京都 あきる野市"),80373 },
{ 13229,_T("東京都 西東京市"),202201 },{ 13303,_T("東京都 西多摩郡瑞穂町"),33102 },
{ 13305,_T("東京都 西多摩郡日の出町"),17404 },{ 13307,_T("東京都 西多摩郡檜原村"),2096 },
{ 13308,_T("東京都 西多摩郡奥多摩町"),5058 },{ 13361,_T("東京都 大島町"),7580 },
{ 13362,_T("東京都 利島村"),343 },{ 13363,_T("東京都 新島村"),2630 },
{ 13364,_T("東京都 神津島村"),1845 },{ 13381,_T("東京都 三宅島三宅村"),2383 },
{ 13382,_T("東京都 御蔵島村"),343 },{ 13401,_T("東京都 八丈島八丈町"),7330 },
{ 13402,_T("東京都 青ヶ島村"),174 },{ 13421,_T("東京都 小笠原村"),3067 },
0
};
for (INT i = 0;; i++)
{
if (item[i].id == 0) break;
ZeroMemory(&lvitm, sizeof(LVITEM));
lvitm.mask = LVIF_TEXT;
lvitm.iItem = pList->GetItemCount();
lvitm.iSubItem = 0;
ZeroMemory(&twk, sizeof(twk));
wsprintf(twk, _T("%d"), item[i].id);
lvitm.pszText = twk;
idx = ListView_InsertItem(pList->GetSafeHwnd(), &lvitm);
//idx = pList->InsertItem(&lvitm);
if (idx == (-1))
{
AfxMessageBox(L"InsertItem Error!!",MB_ICONSTOP);
return;
}
ZeroMemory(&lvitm, sizeof(LVITEM));
lvitm.mask = LVIF_TEXT;
lvitm.iItem = idx;
lvitm.iSubItem = 1;
lvitm.pszText = item[i].name;
ListView_SetItem(pList->GetSafeHwnd(), &lvitm);
//pList->SetItem(&lvitm);
ZeroMemory(&lvitm, sizeof(LVITEM));
lvitm.mask = LVIF_TEXT;
lvitm.iItem = idx;
lvitm.iSubItem = 2;
ZeroMemory(&twk, sizeof(twk));
wsprintf(twk, _T("%d"), item[i].population);
lvitm.pszText = twk;
ListView_SetItem(pList->GetSafeHwnd(), &lvitm);
//pList->SetItem(&lvitm);
}
}
/***********************************************************
WindowProc
リストコントロールのイベント処理
LVN_ITEMCHANGED : リストコントロールに変更があった
LVN_COLUMNCLICK : リストコントロールのヘッダが左クリックされた
***********************************************************/
LRESULT CChildView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
LV_DISPINFO *lvdisp;
NM_LISTVIEW *pNMLV;
CString cs;
int idx;
switch (message)
{
case WM_NOTIFY:
//リストコントロールからのメッセージのみ処理する
if ((int)wParam == D_IDLISTVIEW) {
lvdisp = (LV_DISPINFO *)lParam;
pNMLV = (NM_LISTVIEW *)lParam;
//リストビューを取得
CListCtrl *pListCtrl = (CListCtrl *)GetDlgItem(D_IDLISTVIEW);
//選択されている行のインデックスを取得
idx = pNMLV->iItem;
switch (lvdisp->hdr.code) {
case LVN_ITEMCHANGED:
//選択行の情報を表示する
if ((pNMLV->uChanged & LVIF_STATE) && (pNMLV->uNewState & LVIS_SELECTED)) {
cs.Format(L"%d行目¥r¥n地域コード [%s]¥r¥n市区町村名 [%s]¥r¥n人口 [%s]",
idx+1,pListCtrl->GetItemText(idx, 0),
pListCtrl->GetItemText(idx, 1),
pListCtrl->GetItemText(idx, 2));
AfxMessageBox(cs,MB_ICONINFORMATION);
}
break;
case LVN_COLUMNCLICK:
//iSubItemを参照してヘッダのクリックされた列を表示する
cs.Format(L"ヘッダ行の%d列目が左クリックされました", pNMLV->iSubItem+1);
AfxMessageBox(cs,MB_ICONINFORMATION);
break;
}
}
break;
default:
;
}
return CWnd::WindowProc(message, wParam, lParam);
}
よろしければポチッと押してください
]]>
・フォームにControlをオーナードローします
TextBox×20
OptionButton×60(3個1組でグループ化)
ConboBox×20
Label×20
・フォームのプロパティをスクロールできるよう設定します
ScrollBars(スクロールバーの表示)
ScrollHeight(フォーム全体の高さ)
・クラスモジュール、標準モジュールを追加します
・クラス(WithEvents)でイベントを受け取ります
Class1:OptionButtonクリックイベントのコールバック
Class2:ComboBox選択変更イベントのコールバック
<動作環境>
Microsoft Office 2016
<実行イメージ>
フォームInitializeでコントロールを配置
(テキスト、ラジオ、コンボ、ラベルを20組配置)
<使い方>
フォームを追加します(ID:UserForm1)
ラジオボタンイベント通知クラスを追加します(Class1)
コンボボックスイベント通知クラスを追加します(Class2)
フォーム表示用の標準モジュールを追加します(Module1)
ユーザフォーム表示()を実行するとフォームを表示します
Module1
'/*********************************************
'/ ユーザフォームを表示する
'/*********************************************
Public Sub ユーザフォーム表示()
UserForm1.Show
End Sub
UserForm1
'//イベントを受け取るコントロール
]]>
(1)社員ID(int)、社員名(CString)、通勤費支給(BOOL)を持つクラスを定義
(2)クラスのメンバ変数を operator= でコピーできるようにする
オブジェクトA = オブジェクトB でメンバ変数をコピー
(3)クラスインスタンスを動的配列(std::vector)に operator+ で追加する
(4)追加と同時にソート処理を実施する
オブジェクトA + オブジェクトB でオブジェクトAの動的配列にオブジェクトBを追加
オブジェクトAの動的配列を社員IDの昇順でソート(std::sort)
<実行イメージ>
"出力"ウィンドウに結果を表示します
※表示されていない場合は[表示]メニュー→[出力]
<動作検証&開発環境>
Visual Studio Community 2017
<使い方>
1.プロジェクトの種類でWindowsデスクトップウィザードを選択
2.アプリケーションの種類で「コンソールアプリケーション」を選択
3.共通ヘッダの「MFC」にチェック
4.クラスを追加
クラス名:CShainClass
ファイル名:ShainClass.h
(ShainClass.cppは本サンプルでは使用しません)
5.ソースを追加
ShainClass.h
(1)入力は半角英数のみ、文字数の上限チェックをクラスで実装する
(2)OnEnChangeで半角英数チェックを行う
(3)OnKeyDownで入力文字数の上限チェックを行う
(4)入力制限クラスを複数のエディットボックスに適用する
<実行イメージ>
半角英数チェックと文字数の上限チェックを行う
<動作検証&開発環境>
Visual Studio Community 2017
<使い方>
1.ダイアログベースでMFCApplication1プロジェクトを作成します
2.クラスウィザードでMFCクラスを追加します
基底クラスに「CEdit」を選択
クラス名を「CEditTest」とします
3.クラスウィザードでCEditTestクラスに下記イベントを追加します
OnEnChange : このイベントで半角英数チェックを行います
OnKeyDown : このイベントで上限文字数チェックを行います
4.IDD_MFCAPPLICATION1_DIALOGにエディットボックスを2つ追加します
5.追加したエディットボックスにそれぞれメンバ変数を追加します
・コントロール変数にチェック
・カテゴリ:Control
・変数の種類:CEditTest(CEditTestクラスの変数とする)
・変数名はそれぞれm_Edit1 、 m_Edit2 とします
6.ソースを追加してください
CEditTest.h
CEditTest.cpp
MFCApplication1Dlg.h
MFCApplication1Dlg.cpp
よろしければポチッと押してください
]]>