メニュー関連の関数として、以下がある。
| CreateMenu |
ウィンドウのタイトルバーの下に張り付く横長のメニューを作成するための関数。この関数で作成したメニューに対し、AppendMenuまたはInsertMenuItemで項目を追加する。 |
| CreatePopupMenu |
ポップアップメニュー、つまり縦に開かれるメニューを作成する関数。 |
| AppendMenu |
InsertMenuItemに取って代わられ、いまは互換性のために存在している。
|
| InsertMenuItem | メニューに項目を追加するための関数 |
従って、メニュー作成の手順は、
HMENU hMenuTop = CreateMenu();
としてメニューを作成し、
InsertMenuItem(hMenuTop , ID_MENU_TOP_1, FALSE, &mii1);
InsertMenuItem(hMenuTop , ID_MENU_TOP_2, FALSE, &mii2);
のようにメニュー項目を追加することになる。
最後に
SetMenu(hWnd,hMenuTop);
として、ウィンドウにメニューを関連づける。
ここで、上記mii1はMENUITEMINFO型の構造体の変数であり、メニューのアイテム追加の時に、アイテムの性質を渡すための変数である。
MENUITEMINFOはわかりにくいので、まずここにまとめる。
下記MENUITEMINFOのメンバのうち、どれを使うかをfMaskで指定する。
MENUITEMINFO mii;
| メンバ名 | 指定例 | fMaskの指定 | 説明 |
| mii.cbSize | = sizeof(MENUITEMINFO); | - | MENUITEMINFOのサイズ |
| mii.fMask | = MIIM_ID | MIIM_STRING; | - | 以下のパラメータのうち使用する物 |
| mii.fType | = MFT_RADIOCHECK; | MIIM_FTYPE | アイテムのタイプ |
| mii.fState | = MFS_ENABLED; | MIIM_STATE | アイテムの状態 |
| mii.wID | = 100; //ユーザー定義 | MIIM_ID | アイテムID |
| mii.hSubMenu | = hSubMenu;//ユーザー定義 | MIIM_SUBMENU | サブメニューのハンドル |
| mii.hbmpChecked | = NULL; | MIIM_CHECKMARKS | チェック表示時のビットマップ |
| mii.hbmpUnchecked | = NULL; | MIIM_CHECKMARKS | チェック非表示時のビットマップ |
| mii.dwItemData | = 0;//ユーザー定義 | MIIM_DATA | 任意の32ビット値 |
| mii.dwTypeData | = "ファイル(&F)"; | MIIM_STRING | アイテムの内容 |
| mii.cch | = sizeof("ファイル(&F)" | - | アイテムの文字列の長さ |
| mii.hbmpItem | = NULL; | MIIM_BITMAP | ビットマップハンドル |
例1 ポップアップメニューなし
//////////////////////////////////////////////// HMENU hmenu_top = CreateMenu(); // メニュー作成 const UINT ID_MENU_TOP_1 = 1; const UINT ID_MENU_TOP_2 = 2; //////////////////////////////////////////////// MENUITEMINFO mii; memset(&mii, 0, sizeof(MENUITEMINFO)); mii.cbSize = sizeof(MENUITEMINFO); //////////////////////////////////////////////// mii.fMask = MIIM_ID | MIIM_STRING; mii.wID = ID_MENU_TOP_1; mii.dwTypeData = _T("メニュー1"); InsertMenuItem(hmenu_top, ID_MENU_TOP_1, FALSE, &mii); mii.wID = ID_MENU_TOP_2; mii.dwTypeData = _T("メニュー2"); InsertMenuItem(hmenu_top, ID_MENU_TOP_2, FALSE, &mii); SetMenu(hDlg, hmenu_top);//ウィンドウにメニューを関連づける
例1 ポップアップメニューあり
//////////////////////////////////////////////// HMENU hmenu_top = CreateMenu(); // メニュー作成 const UINT ID_MENU_TOP_1 = 1; const UINT ID_MENU_TOP_2 = 2; HMENU hmenu_Lv1_1 = CreatePopupMenu(); //◆サブメニューの作成 HMENU hmenu_Lv1_2 = CreatePopupMenu(); //◆サブメニューの作成 //////////////////////////////////////////////// MENUITEMINFO mii; memset(&mii, 0, sizeof(MENUITEMINFO)); mii.cbSize = sizeof(MENUITEMINFO); //////////////////////////////////////////////// mii.fMask = MIIM_ID | MIIM_STRING | MIIM_SUBMENU ; mii.wID = ID_MENU_TOP_1; mii.hSubMenu = hmenu_Lv1_1; //◆サブメニューの追加 mii.dwTypeData = _T("メニュー1"); InsertMenuItem(hmenu_top, ID_MENU_TOP_1, FALSE, &mii); mii.wID = ID_MENU_TOP_2; mii.hSubMenu = hmenu_Lv1_2; //◆サブメニューの追加 mii.dwTypeData = _T("メニュー2"); InsertMenuItem(hmenu_top, ID_MENU_TOP_2, FALSE, &mii); SetMenu(hDlg, hmenu_top);//ウィンドウにメニューを関連づける //////////////////////////////////////////////// // ◆サブメニューの項目追加 const UINT ID_MENU_Lv1_1 = 3; const UINT ID_MENU_Lv1_2 = 4; const UINT ID_MENU_Lv1_3 = 5; mii.fMask = MIIM_ID | MIIM_STRING; mii.wID = ID_MENU_Lv1_1; mii.dwTypeData = _T("サブ11"); InsertMenuItem(hmenu_Lv1_1, ID_MENU_Lv1_1, FALSE, &mii); mii.wID = ID_MENU_Lv1_2; mii.dwTypeData = _T("サブ12"); InsertMenuItem(hmenu_Lv1_1, ID_MENU_Lv1_2, FALSE, &mii); mii.wID = ID_MENU_Lv1_3; mii.dwTypeData = _T("サブ13"); InsertMenuItem(hmenu_Lv1_1, ID_MENU_Lv1_3, FALSE, &mii); //////////////////////////////////////////////// const UINT ID_MENU_Lv2_1 = 6; const UINT ID_MENU_Lv2_2 = 7; mii.fMask = MIIM_ID | MIIM_STRING; mii.wID = ID_MENU_Lv2_1; mii.dwTypeData = _T("サブ21"); InsertMenuItem(hmenu_Lv1_2, ID_MENU_Lv2_1, FALSE, &mii); mii.wID = ID_MENU_Lv2_2; mii.dwTypeData = _T("サブ22"); InsertMenuItem(hmenu_Lv1_2, ID_MENU_Lv2_2, FALSE, &mii);
参考文献
http://gurigumi.s349.xrea.com/programming/visualcpp/sdk_menu3.html
Vray for Blenderのテクスチャの中にFresnelが入っている。
http://tofusan.cocolog-nifty.com/blog/2013/03/post-557d.html
フレネル(Fresnel)とは、異なる屈折率を持つ2つの物体の界面において、光が反射する様子のこと
以下、Diffuseのカラーに繋いだ結果。平面だとわかりにくい。
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
球体だととてもわかりやすい。
![]() |
![]() |
![]() |
![]() |
C++のpimplとは何か。
pimplはコーディングテクニックのひとつで、ヘッダファイルから本来公開すべきではない項目を隠すことができるようになる。
#include "ClassTest.h" //エントリーポイント int _tmain(int argc, _TCHAR* argv[]) { CClassTest test; test.Set(100); test.Show(); getchar(); return 0; }
class CClassTest { private: class CClassTest_Impl* p_private;//CClassTestメンバはポインタのみ public: CClassTest(void); ~CClassTest(void); void Show()const; void Set(int val); };
#include "stdafx.h" #include "ClassTest.h" //公開したくない変数や関数をここに置く//////////////////// class CClassTest_Impl{ public: int m_value; }; //公開したいメンバ関数の実装///////////////////////////////////// CClassTest::CClassTest(void) { p_private = new CClassTest_Impl; } CClassTest::~CClassTest(void) { delete p_private; } void CClassTest::Show()const{ printf("%d\n",p_private->m_value); } void CClassTest::Set(int val){ p_private->m_value = val; }
①ヘッダファイルは普通cppファイルに#includeされる形で用いられる。
②#includeはファイルの内容をコピーするプリプロセッサである。
③つまり、CClassTest_ImplクラスをClassTest.hに書いても、ClassTest.cppに書いても、コンパイルの段階では全てClassTest.cppに書いたことになる。
④ならば最初からClassTest.cppに書いてしまえば、CClassTest_Implはcppファイルの中だけで完結する
⑤勿論、CClassTest_Implが他のファイルからも参照されるクラスならヘッダファイルに書かなければならない。
⑥しかし、CClassTest_ImplはCClassTestからしか用いない。従ってヘッダファイルで宣言を公開しておく必要がない。
⑦ClassTest.hではCClassTest_Implのポインタのみを宣言する。ポインタはsizeof(void*)長の変数であり、宣言時にクラスの内容がわからなくてもいい。
⑧こうして、ヘッダファイルから公開したくない項目をすべて隠すことが可能となる
中間管理職トネガワを見ているので久しぶりにカイジも見ているのだが、ついでに映画の実写版も見てみた。
感想を書くと批判の方が多くなってしまうのだが・・・今回に関してだけ言えば、そんなことは全く問題ではない。
なぜならカイジのスピンオフである「中間管理職トネガワ」がナレーション(を筆頭とした諸々のセンスのずれ)のせいでかなり悲惨な作品になってしまったからである。
多分この作品、ハガレンやヘルシングよろしく「中間管理職トネガワ Ultimate」とかで作り直してDVD化するんじゃないかな?←
というわけで実写版カイジの話。
カイジは自堕落なクズだが一方で他人の悪意に敏感な熱血漢でもある。そういうものを目の当たりにした時に彼が叫ぶさまはカイジらしかったと思う。
褒め言葉かと思いきやそうでもない。限定じゃんけん→地下生活(チンチロなし)→Eカードまでを二時間の中にぶち込んでいるのが原因だと思うのだが、確かによく言えば展開が速い。
一方で、一枚のカードを出すのに何分も悩んで堂々巡りしたり、どん底からのひらめきで必死に策を講じたり、そして策を実らせるために仲間と地べたに這いつくばるようにして努力する様は殆ど見られない。実際の所、原作は勝負の瞬間のために何時間も何日も準備する所が見所なので、その点が残念だ。本来カイジ視点で見れば、永遠のように感じる一瞬を固唾をのんで見つめ続けるようなシーンも多い。スピードは必要ないと思う。
利根川や会長は、殺虫剤をかけられた蛆虫がもがき苦しむのを眺めて笑うような感覚で債務者をいたぶるサイコパスである。
どうもこの利根川からはそういう、人を徹底的に見下した感性が伝わってこない。
会長にしても、次元が二けたくらい違うような圧倒的強者の落ち着きが感じられない。
遠藤さえ、鉄骨渡りを見ている投資家たちを見て不快感を示している。そんな感性が残っていてよく出世できたものだ。
やはり彼らには、クズが一周して悟りを開いたような違う世界の生き物であってほしい。
作品冒頭、シェルターを作るために労働者を集めよう、みたいなことを言っていたのだが、それなら劣悪債務者を片っ端からぶち込んでいけばいいだけで、わざわざ恩赦を与える必要はない。
エスポワールはあくまで会長達を楽しませることが主目的ではないだろうか。勿論、船の中で借金をしなければならないので、劣悪債務者昇格システムではあるのだが、強制労働や命がけのギャンブルなんて元々違法(違法と言えば金利がそもそも違法だし)なのだから、借金200万円以上は劣悪債務者ってことにしてしまえば済む話のように思う。
地下に落ちたらビールを奢ろう、という話。アニメ版では遠藤が「大人しく死ぬか、悪あがきして死ぬか」という究極の選択に迫られた時に、カイジから出された妥協案である。そこにはカイジという泥船に乗ってしまった後悔やら、それでも乗り続けるしかない絶望やら、要はドブネズミが逃げるために残しておいた後ろ足で猫に嚙みつくなんて正気の沙汰ではない心境だからこそ格好いいのだが、出世街道から外れただけの実写版遠藤がなぜカイジに乗ったのか・・・。
CreateDialog,DialogBox各関数でダイアログを作成した場合、配置したアイテムのウィンドウハンドルをどのように取得するのか。
これにはWin32APIのGetDlgItem関数を使う。
HWND hcontrol = GetDlgItem( ダイアログボックスのウィンドウハンドル , リソースのID(数値) )
#include <Windows.h> #include "resource.h" //IDD_DIALOG1の定義が入っている #include <tchar.h> //ダイアログプロシージャ INT_PTR CALLBACK DlgWndProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { INT_PTR ret = FALSE; static HWND hbtn; switch (msg) { case WM_INITDIALOG: //初期化時にボタンの名称を変更する hbtn = GetDlgItem(hDlg, IDC_BUTTON1); SetWindowText(hbtn, _T("hello")); ret = TRUE; break; case WM_CLOSE: DestroyWindow(hDlg); PostQuitMessage(0); ret = TRUE; break; } return ret; } //エントリーポイント int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { //ダイアログを作成 HWND hDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), nullptr, (DLGPROC)DlgWndProc); ShowWindow(hDlg, SW_SHOW); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
次に、ハンドルはわかるがリソースIDがわからない場合。
これにはWin32APIのGetDlgCtrlID関数を使う。
int id = GetDlgCtrlID(ウィンドウハンドル)
#include <Windows.h> #include "resource.h" #include <tchar.h> #include <crtdbg.h> //ダイアログプロシージャ INT_PTR CALLBACK DlgWndProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { INT_PTR ret = FALSE; HWND hscr; int id; switch (msg) { case WM_HSCROLL: hscr = (HWND)lp;//WM_HSCROLLのlParamにはハンドルが入っている id = GetDlgCtrlID(hscr);//動かしたスクロールバーのIDを取得 _RPT1(_CRT_WARN, "ID=%d\n", id); break; case WM_CLOSE: DestroyWindow(hDlg); PostQuitMessage(0); ret = TRUE; break; } return ret; } //エントリーポイント int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { //ダイアログを作成 HWND hDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), nullptr, (DLGPROC)DlgWndProc); ShowWindow(hDlg, SW_SHOW); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
CUDAでグラデーション画像を作成する。
勉強中なので突っ込みどころは多そうだが、気をつけたところは、
・1ブロック内のスレッド数を512以下にする
・1ブロック内のスレッド数を32の倍数にする(ワープの単位)
#include "cuda_runtime.h" #include "device_launch_parameters.h" #include <stdio.h> #include <cstring> void pnmP3_Write(const char* const fname, const int vmax, const int width, const int height, const unsigned char* const p); /////////////////////////////////////////////// // GPU側 ////////////////////////////////////// __global__ void gradation(unsigned char* c,const int N) { //アクセス法 //このスレッドが担当する画素の位置を二次元座標で求める size_t xpos = blockIdx.x * blockDim.x + threadIdx.x; size_t ypos = blockIdx.y * blockDim.y + threadIdx.y; if (xpos < N && ypos < N) { size_t pos = N*ypos + xpos;//二次元座標を一次元座標に float R = ypos / (float)N; float G = (N - ypos) / (float)N; float B = xpos / (float)N; c[pos * 3 + 0] = R * 255;//0~255にして色書き込み c[pos * 3 + 1] = G * 255; c[pos * 3 + 2] = B * 255; } } ////////////////////////////////////////// //CPU側エントリーポイント/////////////////// int main(void) { //作成画像 N × N × 3 const int N = 1000; //16×16の領域に分けて計算する dim3 block(16, 16); //グリッド数 dim3 grid(N / 16+1, N / 16 + 1); unsigned char* p_gpu;//GPU側メモリ確保 cudaMalloc((void**)&p_gpu, N * N * 3); gradation << <grid, block >> > (p_gpu,N); //CPU側メモリ確保 unsigned char *p_cpu = new unsigned char[N * N * 3]; //GPU→CPU側へメモリコピー cudaMemcpy(p_cpu, p_gpu, N*N*3, cudaMemcpyDeviceToHost); cudaFree(p_gpu); //ファイル出力 pnmP3_Write("C:\\test\\hello.ppm", 255, N, N, p_cpu); delete[] p_cpu; getchar(); } ///////////////////////////////////////////// //画像ファイル書き出し///////////////////////// //! @brief PPM(RGB各1byte,カラー,テキスト)を書き込む //! @param [in] fname ファイル名 //! @param [in] vmax 全てのRGBの中の最大値 //! @param [in] width 画像の幅 //! @param [in] height 画像の高さ //! @param [in] p 画像のメモリへのアドレス //! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む void pnmP3_Write(const char* const fname, const int vmax, const int width, const int height, const unsigned char* const p) { // PPM ASCII FILE* fp = fopen(fname, "wb"); fprintf(fp, "P3\n%d %d\n%d\n", width, height, vmax); size_t k = 0; for (size_t i = 0; i < (size_t)height; i++) { for (size_t j = 0; j < (size_t)width; j++) { fprintf(fp, "%d %d %d ", p[k * 3 + 0], p[k * 3 + 1], p[k * 3 + 2]); k++; } fprintf(fp, "\n"); } fclose(fp); }
元々こちらのサイトで知ったのだが、いかんせんダウンロードがわかりにくいのでここに書いておく
① https://beemuse.com/ へ行く
② 右上の「Install」のGitHub projectをクリック
https://github.com/itmustbe/beemuse
③ 下の方のREADME.mdの枠の中にある https://github.com/itmustbe/package-beemuseをクリック
https://github.com/itmustbe/package-beemuse
④ 中央のファイル一覧の中の「dist」をクリック
https://github.com/itmustbe/package-beemuse/tree/master/dist
⑤ beemuse.css をダウンロード
beemuse.css内、 .stitchの部分をいろいろ変えると色を変えられる
技術系の記事だけで三日ごとに更新するのはさすがにきつすぎることが最近わかってきたので(一つの記事が薄くなりすぎる)、色々混ぜることにする。
そもそも、vrayのノードの組み合わせの記事とか、殆ど文字にならないんだけれども、cycles等々と違って巷に答えが転がってないので、ガラスにcausticsつけるのに一ヶ月調査したからね。いやマジで。それでvrayの試用期間終わってよくわからんうちに買う羽目になったわけで、それを三日ごとに公開してりゃネタも無くなるのである。
といいつつBlender+Cycles。なぜvrayにしなかったかというと、PlantFactory→vrayの変換がまだできなかったから。まあやればできることはわかっているのだけど面倒くさすぎるうえに多分結果があまり変わらないから。
月は: https://free3d.com/3d-model/moon-photorealistic-2k-853071.html から。
木はPlantFactoryで自作。
かなりこだわった草は殆ど見えない←
背景は透明でレンダリングして後からgimpでグラデーションをつけている。
std::shared_ptrを使うに当たり、自分のポインタをshared_ptrで誰かに渡したいことがある。
当然thisを使うのだが、
auto ptr = shared_ptr(this); // NG
こんなことをしてはいけない。thisを使いたい場合、そのクラスをenable_shared_from_thisクラスからpublic継承し、shared_from_this関数を用いてthisを取得する必要がある。その際、以下のことに気を付ける必要がある
①.thisを使いたいときはenable_shared_from_thisを継承する
②.コンストラクタの中でshared_from_thisを使ってはいけない
③.自分自身がshared_ptrで管理されていなければならない
#include <memory> #include <iostream> // ① OK enable_shared_from_this を使う class myData: public std::enable_shared_from_this<myData>{ int i; public: myData(){ //②NG コンストラクタでshared_from_thisを使ってはいけない std::cout << shared_from_this()->i << std::endl; }; void func(){ //②OK thisの取得にshared_from_thisを使う std::cout << shared_from_this()->i << std::endl; } }; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// int _tmain(int argc, _TCHAR* argv[]) { //③ enable_shared_from_thisを使う場合は、自信もshared_ptrで管理されなければならない myData data1;// ③ NG myData *data2 = new myData;// ③ NG // ③ OK std::shared_ptr<myData> data3 = std::shared_ptr<myData>( new myData ); // ③ OK std::shared_ptr<myData> data4 = std::make_shared<myData>(); data4->func(); getchar(); return 0; }