mmage.cpp 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. // WonW32.cpp : DLL アプリケーション用のエントリ ポイントを定義します。
  2. //
  3. //#define SHOW_RENDERTIME
  4. #define INITGUID
  5. #include "mmage.h"
  6. #include <windows.h>
  7. #include <commctrl.h>
  8. #include <tchar.h>
  9. #include <ctype.h>
  10. #define DIRECTDRAW_VERSION 0x0500
  11. #define DIRECTINPUT_VERSION 0x0500
  12. #include <ddraw.h>
  13. #include <dinput.h>
  14. #include "../resource/resource.h"
  15. #include "preference.h"
  16. #include "../mmvm/mmvm.h"
  17. extern "C" {
  18. #include "../wonx/wonx.h"
  19. #include "../wonx/wonxdisplay.h"
  20. #include "../wonx/xdisplay.h"
  21. #include "../wonx/xdisplayp.h"
  22. #include "../wonx/wwlcdpanel.h"
  23. #include "../cpu/mytypes.h"
  24. #include "../cpu/global.h"
  25. #include "../cpu/cpu.h"
  26. }
  27. typedef struct {
  28. WonXDisplay wonx_display;
  29. XDisplay x_display;
  30. WWLCDPanel ww_lcd_panel;
  31. WWScreen ww_screen[2];
  32. WWDisplay ww_display;
  33. } WONXOBJECT, *LPWONXOBJECT;
  34. #define MAX_LOADSTRING 100
  35. static WONW32CONTEXT context;
  36. static WONXOBJECT wonxobject;
  37. LPWONW32CONTEXT wonw32ctx = &context;
  38. static LPWONXOBJECT wonxobj = &wonxobject;
  39. static HBITMAP titlebmp;
  40. static HWND statusbar;
  41. #define LCD_SLEEP 0
  42. #define LCD_VERTICAL 1
  43. #define LCD_HORIZONTAL 2
  44. #define LCD_AUX1 3
  45. #define LCD_AUX2 4
  46. #define LCD_AUX3 5
  47. static HICON lcdseg[6][2];
  48. BOOL ddInit;
  49. static LPDIRECTDRAW lpDD;
  50. static LPDIRECTDRAWSURFACE lpDDSPrimary;
  51. static LPDIRECTDRAWSURFACE screen[2];
  52. static LPDIRECTDRAWCLIPPER lpClip;
  53. #define COLORKEY (RGB(0x00, 0x00, 0x00))
  54. #define SafeRelease(x) if (x) { x->Release(); x=NULL;}
  55. extern "C" {
  56. extern LPDIRECTINPUTDEVICE lpDIDevice;
  57. }
  58. LPDIRECTINPUT lpDI;
  59. LPDIRECTINPUTDEVICE lpDIDevice;
  60. static COLORREF w32colors[] = {
  61. COLORKEY,
  62. RGB(0xff, 0xff, 0xff),
  63. RGB(0xef, 0xef, 0xef),
  64. RGB(0xdf, 0xdf, 0xdf),
  65. RGB(0xcf, 0xcf, 0xcf),
  66. RGB(0xbf, 0xbf, 0xbf),
  67. RGB(0xaf, 0xaf, 0xaf),
  68. RGB(0x9f, 0x9f, 0x9f),
  69. RGB(0x8f, 0x8f, 0x8f),
  70. RGB(0x7f, 0x7f, 0x7f),
  71. RGB(0x6f, 0x6f, 0x6f),
  72. RGB(0x5f, 0x5f, 0x5f),
  73. RGB(0x4f, 0x4f, 0x4f),
  74. RGB(0x3f, 0x3f, 0x3f),
  75. RGB(0x2f, 0x2f, 0x2f),
  76. RGB(0x1f, 0x1f, 0x1f),
  77. RGB(0x0f, 0x0f, 0x0f),
  78. };
  79. static BYTE ddclrs[17][4];
  80. static BYTE ddclrkey[4];
  81. static int bytesPerPixel;
  82. static LONG pitch[2];
  83. static TCHAR szTitle[MAX_LOADSTRING]; // タイトル バー テキスト
  84. static TCHAR szWindowClass[MAX_LOADSTRING]; // タイトル バー テキスト
  85. static ATOM MyRegisterClass( HINSTANCE hInstance );
  86. static BOOL InitInstance( HINSTANCE, int );
  87. static LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
  88. static LRESULT CALLBACK About( HWND, UINT, WPARAM, LPARAM );
  89. static LRESULT CALLBACK License( HWND, UINT, WPARAM, LPARAM );
  90. static void W32Display_DrawLCDWindow(HWND hWnd, WonXDisplay display);
  91. static void DrawScreen(LPBYTE surfm, int screenno, LONG pitch);
  92. static void DrawSprite(LPBYTE surfm, WWSprite sprite, LONG pitch);
  93. static BOOL InitDDraw();
  94. static BOOL InitDInput();
  95. static int GetMaskInfo(DWORD bitmask, int *lpShift);
  96. static void SetWindowSize();
  97. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  98. MSG msg;
  99. HACCEL hAccelTable;
  100. int i, skip = 0;
  101. int drawline;
  102. DDSURFACEDESC lockedSurface[2];
  103. RECT dr;
  104. RECT sr[2];
  105. DDBLTFX ddbltfx;
  106. GetCurrentDirectory(MAX_PATH, mmconfig->workingdir);
  107. LoadConfig();
  108. if(!CreateVM())
  109. return FALSE;
  110. if (!WonX_IsCreated())
  111. WonX_Create();
  112. wonxobj->wonx_display = WonX_GetWonXDisplay();
  113. wonxobj->x_display = WonXDisplay_GetXDisplay(wonxobj->wonx_display);
  114. wonxobj->ww_display = WonXDisplay_GetWWDisplay(wonxobj->wonx_display);
  115. wonxobj->ww_lcd_panel = WWDisplay_GetLCDPanel(wonxobj->ww_display);
  116. wonxobj->ww_screen[0] = WWDisplay_GetScreen(wonxobj->ww_display, 0);
  117. wonxobj->ww_screen[1] = WWDisplay_GetScreen(wonxobj->ww_display, 1);
  118. LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
  119. LoadString(hInstance, IDC_MMAGE, szWindowClass, MAX_LOADSTRING);
  120. MyRegisterClass( hInstance );
  121. if( !InitInstance( hInstance, nCmdShow ) )
  122. {
  123. return FALSE;
  124. }
  125. hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MMAGE);
  126. ddInit = InitDDraw();
  127. if(!ddInit) {
  128. MessageBox(wonw32ctx->hWnd, "DirectDraw の初期化に失敗しました。", NULL, MB_OK);
  129. return FALSE;
  130. }
  131. if(!InitDInput()) {
  132. MessageBox(wonw32ctx->hWnd, "DirectInput の初期化に失敗しました。", NULL, MB_OK);
  133. return TRUE;
  134. }
  135. wonw32ctx->syncperiod = 1000/75;
  136. wonw32ctx->syncevent = CreateEvent(NULL, TRUE, FALSE, NULL);
  137. wonw32ctx->running = FALSE;
  138. wonw32ctx->loaded = FALSE;
  139. XDisplay_SetColorMapPrint(wonxobj->x_display, 0);
  140. XDisplay_SetPalettePrint(wonxobj->x_display, 0);
  141. XDisplay_SetCharacterPrint(wonxobj->x_display, 0);
  142. XDisplay_SetSpritePrint(wonxobj->x_display, 0);
  143. wonw32ctx->title = CreateCompatibleDC(GetDC(wonw32ctx->hWnd));
  144. titlebmp = (HBITMAP)LoadBitmap(wonw32ctx->hInst, MAKEINTRESOURCE(IDB_TITLE));
  145. SelectObject(wonw32ctx->title, titlebmp);
  146. InvalidateRect(wonw32ctx->hWnd, NULL, FALSE);
  147. UpdateWindow(wonw32ctx->hWnd);
  148. lockedSurface[0].dwSize = sizeof(lockedSurface[0]);
  149. lockedSurface[1].dwSize = sizeof(lockedSurface[1]);
  150. if(lstrlen(lpCmdLine)) {
  151. LPTSTR str;
  152. TCHAR filename[MAX_PATH + 1];
  153. BOOL quote = FALSE;
  154. str = lpCmdLine;
  155. i = 0;
  156. while(*str) {
  157. if(_istspace(*str) && !quote) {
  158. *str = TEXT('\0');
  159. str++;
  160. break;
  161. } else if(quote && (*str == TEXT('\"') || *str == TEXT('\''))) {
  162. quote = FALSE;
  163. } else if(!quote && (*str == TEXT('\"') || *str == TEXT('\''))) {
  164. quote = TRUE;
  165. } else {
  166. filename[i] = *str;
  167. i++;
  168. }
  169. str++;
  170. }
  171. filename[i] = TEXT('\0');
  172. OpenAndRun(filename, str);
  173. }
  174. DragAcceptFiles(wonw32ctx->hWnd,TRUE);
  175. drawline = 0;
  176. ZeroMemory(&ddbltfx, sizeof(ddbltfx));
  177. ddbltfx.dwSize = sizeof(ddbltfx);
  178. sr[MMCONFIG_HORIZONTAL].top = sr[MMCONFIG_HORIZONTAL].left = 0;
  179. sr[MMCONFIG_HORIZONTAL].right = wonw32ctx->ww_lcd_width;
  180. sr[MMCONFIG_HORIZONTAL].bottom = wonw32ctx->ww_lcd_height;
  181. sr[MMCONFIG_VERTICAL].top = sr[MMCONFIG_VERTICAL].left = 0;
  182. sr[MMCONFIG_VERTICAL].right = wonw32ctx->ww_lcd_height;
  183. sr[MMCONFIG_VERTICAL].bottom = wonw32ctx->ww_lcd_width;
  184. #ifdef SHOW_RENDERTIME
  185. DWORD oldt, t;
  186. BOOL showrt = TRUE;
  187. TCHAR rtmsg[256];
  188. #endif
  189. // メイン メッセージ ループ:
  190. while(TRUE) {
  191. WWSprite sprite;
  192. POINT p;
  193. LPBYTE border;
  194. // ウィンドウがアクティブでないとき
  195. if(!wonw32ctx->active || (wonw32ctx->active && !wonw32ctx->running)) {
  196. if(GetMessage(&msg, NULL, 0, 0)) {
  197. if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) ) {
  198. TranslateMessage( &msg );
  199. DispatchMessage( &msg );
  200. }
  201. }
  202. if(msg.message == WM_QUIT)
  203. break;
  204. continue;
  205. }
  206. // ウィンドウがアクティブなとき
  207. if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  208. if(msg.message == WM_QUIT)
  209. break;
  210. if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) ) {
  211. TranslateMessage( &msg );
  212. DispatchMessage( &msg );
  213. }
  214. } else {
  215. #ifdef SHOW_RENDERTIME
  216. oldt = timeGetTime();
  217. #endif
  218. screen[1]->Lock(NULL, &lockedSurface[0], DDLOCK_WAIT|DDLOCK_NOSYSLOCK, NULL);
  219. pitch[0] = lockedSurface[0].lPitch;
  220. screen[2]->Lock(NULL, &lockedSurface[1], DDLOCK_WAIT|DDLOCK_NOSYSLOCK, NULL);
  221. pitch[1] = lockedSurface[1].lPitch;
  222. DrawScreen((BYTE *)lockedSurface[0].lpSurface, 0, pitch[0]);
  223. DrawScreen((BYTE *)lockedSurface[1].lpSurface, 1, pitch[1]);
  224. if(WWDisplay_GetSpriteEnable(wonxobj->ww_display)) {
  225. for(i = WWDisplay_GetSpriteCount(wonxobj->ww_display) - 1; i >= 0; i--) {
  226. sprite = WWDisplay_GetSprite(wonxobj->ww_display, i + WWDisplay_GetSpriteStart(wonxobj->ww_display));
  227. if(!WWSprite_GetPriority(sprite)) {
  228. DrawSprite((BYTE *)lockedSurface[0].lpSurface, sprite, pitch[0]);
  229. } else {
  230. DrawSprite((BYTE *)lockedSurface[1].lpSurface, sprite, pitch[1]);
  231. }
  232. }
  233. }
  234. screen[1]->Unlock(lockedSurface[0].lpSurface);
  235. screen[2]->Unlock(lockedSurface[1].lpSurface);
  236. border = (LPBYTE)&ddclrs[WWColorMap_GetLCDColor(WWDisplay_GetColorMap(wonxobj->ww_display), WWDisplay_GetBorder(wonxobj->ww_display)) + 1];
  237. ddbltfx.dwFillColor = (border[0] << 24)
  238. | (border[1] << 16)
  239. | (border[2] << 8)
  240. | border[3];
  241. screen[0]->Blt(NULL, NULL, NULL, DDBLT_WAIT|DDBLT_COLORFILL, &ddbltfx);
  242. screen[0]->BltFast(0, 0, screen[1], NULL, DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY);
  243. screen[0]->BltFast(0, 0, screen[2], NULL, DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY);
  244. ZeroMemory(&p, sizeof(p));
  245. ClientToScreen(wonw32ctx->hWnd, &p);
  246. dr.left = p.x;
  247. dr.top = p.y;
  248. dr.right = dr.left + wonw32ctx->winwidth + 1;
  249. dr.bottom = dr.top + wonw32ctx->winheight + 1;
  250. lpDDSPrimary->Blt(&dr, screen[0], &sr[mmconfig->horizontal], DDBLT_WAIT, NULL);
  251. PulseEvent(wonw32ctx->syncevent);
  252. #ifdef SHOW_RENDERTIME
  253. if(showrt) {
  254. t = timeGetTime();
  255. wsprintf(rtmsg, TEXT("1 フレーム描画にかかった時間は %d msec"), t - oldt);
  256. MessageBox(wonw32ctx->hWnd, rtmsg, TEXT("描画時間"), MB_OK);
  257. showrt = FALSE;
  258. }
  259. #endif
  260. }
  261. }
  262. if(wonw32ctx->running)
  263. StopExecution(1000);
  264. DeleteObject(titlebmp);
  265. DeleteDC(wonw32ctx->title);
  266. SafeRelease(lpDI);
  267. SafeRelease(lpDIDevice);
  268. for(i = 2; i >= 0; i--) {
  269. SafeRelease(screen[i]);
  270. }
  271. SafeRelease(lpDDSPrimary);
  272. SafeRelease(lpDD);
  273. CloseHandle(wonw32ctx->syncevent);
  274. if(wonw32ctx->hWnd != INVALID_HANDLE_VALUE)
  275. DestroyWindow(wonw32ctx->hWnd);
  276. free(memory);
  277. SaveConfig();
  278. return msg.wParam;
  279. }
  280. static BOOL InitDDraw() {
  281. DDSURFACEDESC ddsd;
  282. DDPIXELFORMAT ddpf;
  283. DDCOLORKEY key;
  284. int rsz, gsz, bsz;
  285. int rsh, gsh, bsh;
  286. int r, g, b;
  287. DWORD compiledPixel;
  288. int i;
  289. HINSTANCE dddll;
  290. typedef HRESULT (WINAPI *DDC)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter);
  291. DDC ddc;
  292. dddll = LoadLibrary(TEXT("ddraw.dll"));
  293. ddc = (DDC)GetProcAddress(dddll, TEXT("DirectDrawCreate"));
  294. if(!ddc)
  295. return FALSE;
  296. if(ddc(NULL, &lpDD, NULL) != DD_OK) {
  297. return FALSE;
  298. }
  299. if(lpDD->SetCooperativeLevel(wonw32ctx->hWnd, DDSCL_NORMAL) != DD_OK) {
  300. return FALSE;
  301. }
  302. if(lpDD->CreateClipper(NULL, &lpClip, NULL) != DD_OK) {
  303. return FALSE;
  304. }
  305. lpClip->SetHWnd(0, wonw32ctx->hWnd);
  306. ZeroMemory(&ddsd, sizeof(ddsd));
  307. ddsd.dwSize = sizeof(ddsd);
  308. ddsd.dwFlags = DDSD_CAPS;
  309. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  310. if(lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL) != DD_OK) {
  311. return FALSE;
  312. }
  313. lpDDSPrimary->SetClipper(lpClip);
  314. ZeroMemory(&ddsd, sizeof(ddsd));
  315. ddsd.dwSize = sizeof(ddsd);
  316. ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  317. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  318. ddsd.dwWidth = ddsd.dwHeight = max(wonw32ctx->ww_lcd_width, wonw32ctx->ww_lcd_height);
  319. for(i = 0; i < 3; i++) {
  320. if(lpDD->CreateSurface(&ddsd, &screen[i], NULL) != DD_OK) {
  321. return FALSE;
  322. }
  323. }
  324. // Caliculate compiled pixel value for surface
  325. ZeroMemory(&ddpf, sizeof(ddpf));
  326. ddpf.dwSize = sizeof(ddpf);
  327. lpDDSPrimary->GetPixelFormat(&ddpf);
  328. bytesPerPixel = ddpf.dwRGBBitCount / 8;
  329. if(bytesPerPixel == 1) {
  330. MessageBox(wonw32ctx->hWnd, "256 色モードでは動作しません。", NULL, MB_OK);
  331. return FALSE;
  332. }
  333. rsz = GetMaskInfo(ddpf.dwRBitMask, &rsh);
  334. gsz = GetMaskInfo(ddpf.dwGBitMask, &gsh);
  335. bsz = GetMaskInfo(ddpf.dwBBitMask, &bsh);
  336. for(i = 0; i < 17; i++) {
  337. r = GetRValue(w32colors[i]);
  338. g = GetGValue(w32colors[i]);
  339. b = GetBValue(w32colors[i]);
  340. r >>= (8-rsz);
  341. g >>= (8-gsz);
  342. b >>= (8-bsz);
  343. r <<= rsh;
  344. g <<= gsh;
  345. b <<= bsh;
  346. compiledPixel = (DWORD)(r | g | b);
  347. ddclrs[i][3] = (BYTE) compiledPixel;
  348. ddclrs[i][2] = (BYTE)(compiledPixel >>= 8);
  349. ddclrs[i][1] = (BYTE)(compiledPixel >>= 8);
  350. ddclrs[i][0] = (BYTE)(compiledPixel >>= 8);
  351. }
  352. r = GetRValue(COLORKEY);
  353. g = GetGValue(COLORKEY);
  354. b = GetBValue(COLORKEY);
  355. r >>= (8-rsz);
  356. g >>= (8-gsz);
  357. b >>= (8-bsz);
  358. r <<= rsh;
  359. g <<= gsh;
  360. b <<= bsh;
  361. compiledPixel = (DWORD)(r | g | b);
  362. for(i = 0; i < 3; i++) {
  363. key.dwColorSpaceHighValue = key.dwColorSpaceLowValue = compiledPixel;
  364. screen[i]->SetColorKey(DDCKEY_SRCBLT, &key);
  365. }
  366. ddclrkey[3] = (BYTE) compiledPixel;
  367. ddclrkey[2] = (BYTE)(compiledPixel >>= 8);
  368. ddclrkey[1] = (BYTE)(compiledPixel >>= 8);
  369. ddclrkey[0] = (BYTE)(compiledPixel >>= 8);
  370. return TRUE;
  371. }
  372. static BOOL InitDInput() {
  373. HINSTANCE didll;
  374. typedef HRESULT (WINAPI *DICA)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter);
  375. DICA dica;
  376. didll = LoadLibrary(TEXT("dinput.dll"));
  377. dica = (DICA)GetProcAddress(didll, TEXT("DirectInputCreateA"));
  378. if(!dica)
  379. return FALSE;
  380. if(FAILED((dica)(wonw32ctx->hInst, DIRECTINPUT_VERSION, &lpDI, NULL))) {
  381. return FALSE;
  382. }
  383. if(FAILED(lpDI->CreateDevice(GUID_SysKeyboard, &lpDIDevice, NULL))) {
  384. return FALSE;
  385. }
  386. if(FAILED(lpDIDevice->SetDataFormat(&c_dfDIKeyboard))) {
  387. return FALSE;
  388. }
  389. if(FAILED(lpDIDevice->SetCooperativeLevel(wonw32ctx->hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE))) {
  390. return FALSE;
  391. }
  392. lpDIDevice->Acquire();
  393. return TRUE;
  394. }
  395. static int GetMaskInfo(DWORD bitmask, int *lpShift) {
  396. int precision, shift;
  397. precision = shift = 0;
  398. // count the zeros on right hand side
  399. while(!(bitmask & 0x01L)) {
  400. bitmask >>= 1;
  401. shift++;
  402. }
  403. // count the ones on right hand side
  404. while(bitmask & 0x01L) {
  405. bitmask >>= 1;
  406. precision++;
  407. }
  408. *lpShift = shift;
  409. return precision;
  410. }
  411. //
  412. // 関数: MyRegisterClass()
  413. //
  414. // 用途: ウィンドウ クラスの登録
  415. //
  416. // コメント:
  417. //
  418. // この関数およびその使用はこのコードを Windows 95 で先に追加された
  419. // 'RegisterClassEx' 関数と Win32 システムの互換性を保持したい場合に
  420. // のみ必要となります。アプリケーションが、アプリケーションに関連付け
  421. // られたスモール アイコンを取得できるよう、この関数を呼び出すことは
  422. // 重要です。
  423. //
  424. ATOM MyRegisterClass( HINSTANCE hInstance )
  425. {
  426. WNDCLASSEX wcex;
  427. wcex.cbSize = sizeof(WNDCLASSEX);
  428. wcex.style = CS_HREDRAW | CS_VREDRAW;
  429. wcex.lpfnWndProc = (WNDPROC)WndProc;
  430. wcex.cbClsExtra = 0;
  431. wcex.cbWndExtra = 0;
  432. wcex.hInstance = hInstance;
  433. wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MMAGE));
  434. wcex.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
  435. wcex.hbrBackground = (HBRUSH)NULL;
  436. wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MMAGE);
  437. wcex.lpszClassName = szWindowClass;
  438. wcex.hIconSm = LoadIcon((HINSTANCE)wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
  439. return RegisterClassEx( &wcex );
  440. }
  441. //
  442. // 関数: InitInstance(HANDLE, int)
  443. //
  444. // 用途: インスタンス ハンドルの保存とメイン ウィンドウの作成
  445. //
  446. // コメント:
  447. //
  448. // この関数では、インスタンス ハンドルをグローバル変数に保存し、プログラムの
  449. // メイン ウィンドウを作成し表示します。
  450. //
  451. BOOL InitInstance( HINSTANCE hInstance, int nCmdShow )
  452. {
  453. WWLCDPanel ww_lcd_panel;
  454. INITCOMMONCONTROLSEX icce;
  455. ZeroMemory(&icce, sizeof(icce));
  456. icce.dwSize = sizeof(icce);
  457. icce.dwICC = ICC_DATE_CLASSES | ICC_WIN95_CLASSES;
  458. InitCommonControlsEx(&icce);
  459. wonw32ctx->hInst = hInstance; // グローバル変数にインスタンス ハンドルを保存します
  460. ww_lcd_panel = WWDisplay_GetLCDPanel(WonXDisplay_GetWWDisplay(WonX_GetWonXDisplay()));
  461. wonw32ctx->ww_lcd_width = WWLCDPanel_GetWidth(ww_lcd_panel);
  462. wonw32ctx->ww_lcd_height = WWLCDPanel_GetHeight(ww_lcd_panel);
  463. wonw32ctx->hWnd = CreateWindow(szWindowClass, THIS_APP_TITLE, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, CW_USEDEFAULT, 0,
  464. CW_USEDEFAULT, 0,
  465. NULL, NULL, hInstance, NULL);
  466. if( !wonw32ctx->hWnd ) {
  467. return FALSE;
  468. }
  469. lcdseg[LCD_SLEEP][0] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_SLEEPOFF));
  470. lcdseg[LCD_VERTICAL][0]= LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_VERTICALOFF));
  471. lcdseg[LCD_HORIZONTAL][0] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_HORIZONTALOFF));
  472. lcdseg[LCD_AUX1][0] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_AUX1OFF));
  473. lcdseg[LCD_AUX2][0] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_AUX2OFF));
  474. lcdseg[LCD_AUX3][0] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_AUX3OFF));
  475. lcdseg[LCD_SLEEP][1] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_SLEEP));
  476. lcdseg[LCD_VERTICAL][1]= LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_VERTICAL));
  477. lcdseg[LCD_HORIZONTAL][1] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_HORIZONTAL));
  478. lcdseg[LCD_AUX1][1] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_AUX1));
  479. lcdseg[LCD_AUX2][1] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_AUX2));
  480. lcdseg[LCD_AUX3][1] = LoadIcon(wonw32ctx->hInst, MAKEINTRESOURCE(IDI_AUX3));
  481. statusbar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM,
  482. NULL, wonw32ctx->hWnd, 0);
  483. SendMessage(statusbar, SB_SETMINHEIGHT, (WPARAM)16, 0);
  484. if(!statusbar) {
  485. return FALSE;
  486. }
  487. SetWindowSize();
  488. switch(mmconfig->viewsize) {
  489. case 1:
  490. CheckMenuRadioItem(GetMenu(wonw32ctx->hWnd), IDM_X1, IDM_X4, IDM_X1, MF_BYCOMMAND);
  491. break;
  492. case 2:
  493. CheckMenuRadioItem(GetMenu(wonw32ctx->hWnd), IDM_X1, IDM_X4, IDM_X2, MF_BYCOMMAND);
  494. break;
  495. case 3:
  496. CheckMenuRadioItem(GetMenu(wonw32ctx->hWnd), IDM_X1, IDM_X4, IDM_X3, MF_BYCOMMAND);
  497. break;
  498. case 4:
  499. CheckMenuRadioItem(GetMenu(wonw32ctx->hWnd), IDM_X1, IDM_X4, IDM_X4, MF_BYCOMMAND);
  500. break;
  501. }
  502. if(mmconfig->horizontal)
  503. CheckMenuRadioItem(GetMenu(wonw32ctx->hWnd), IDM_HORIZONTAL, IDM_VERTICAL, IDM_HORIZONTAL, MF_BYCOMMAND);
  504. else
  505. CheckMenuRadioItem(GetMenu(wonw32ctx->hWnd), IDM_HORIZONTAL, IDM_VERTICAL, IDM_VERTICAL, MF_BYCOMMAND);
  506. ShowWindow( wonw32ctx->hWnd, nCmdShow );
  507. UpdateWindow( wonw32ctx->hWnd );
  508. return TRUE;
  509. }
  510. void SetWindowSize() {
  511. int width, height;
  512. RECT r;
  513. wonw32ctx->winwidth = (mmconfig->horizontal ? wonw32ctx->ww_lcd_width : wonw32ctx->ww_lcd_height) * mmconfig->viewsize;
  514. wonw32ctx->winheight = (mmconfig->horizontal ? wonw32ctx->ww_lcd_height : wonw32ctx->ww_lcd_width) * mmconfig->viewsize;
  515. GetWindowRect(statusbar, &r);
  516. width = wonw32ctx->winwidth + GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
  517. height = wonw32ctx->winheight + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYFIXEDFRAME) * 2
  518. + (r.bottom - r.top);
  519. SetWindowPos(wonw32ctx->hWnd, 0, 0, 0, width, height, SWP_NOMOVE|SWP_NOZORDER);
  520. }
  521. //
  522. // 関数: WndProc(HWND, unsigned, WORD, LONG)
  523. //
  524. // 用途: メイン ウィンドウのメッセージを処理します。
  525. //
  526. // WM_COMMAND - アプリケーション メニューの処理
  527. // WM_PAINT - メイン ウィンドウの描画
  528. // WM_DESTROY - 終了メッセージの通知とリターン
  529. //
  530. //
  531. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  532. {
  533. int wmId, wmEvent;
  534. BOOL handled = TRUE;
  535. HMENU menu;
  536. HDROP hdrop;
  537. TCHAR drpfile[MAX_PATH + 1];
  538. int sbsize[2];
  539. LPDRAWITEMSTRUCT lpdi;
  540. menu = GetMenu(hWnd);
  541. switch( message )
  542. {
  543. case WM_COMMAND:
  544. wmId = LOWORD(wParam);
  545. wmEvent = HIWORD(wParam);
  546. // メニュー選択の解析:
  547. switch( wmId )
  548. {
  549. case IDM_ABOUT:
  550. DialogBox(wonw32ctx->hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
  551. break;
  552. case IDM_LICENSE:
  553. DialogBox(wonw32ctx->hInst, (LPCTSTR)IDD_LICENSE, hWnd, (DLGPROC)License);
  554. break;
  555. case IDM_EXIT:
  556. PostQuitMessage( 0 );
  557. break;
  558. case IDM_OPEN:
  559. OpenDlgAndRun();
  560. break;
  561. case IDM_RESTART:
  562. if(!wonw32ctx->running && wonw32ctx->loaded)
  563. Restart();
  564. break;
  565. case IDM_STOP:
  566. if(wonw32ctx->running)
  567. StopExecution(5000);
  568. break;
  569. case IDM_OPENWEB:
  570. ShellExecute(NULL, NULL, THIS_APP_URL, NULL, NULL, SW_SHOWNORMAL);
  571. break;
  572. case IDM_X1:
  573. mmconfig->viewsize = 1;
  574. SetWindowSize();
  575. CheckMenuRadioItem(menu, IDM_X1, IDM_X4, IDM_X1, MF_BYCOMMAND);
  576. break;
  577. case IDM_X2:
  578. mmconfig->viewsize = 2;
  579. SetWindowSize();
  580. CheckMenuRadioItem(menu, IDM_X1, IDM_X4, IDM_X2, MF_BYCOMMAND);
  581. break;
  582. case IDM_X3:
  583. mmconfig->viewsize = 3;
  584. SetWindowSize();
  585. CheckMenuRadioItem(menu, IDM_X1, IDM_X4, IDM_X3, MF_BYCOMMAND);
  586. break;
  587. case IDM_X4:
  588. mmconfig->viewsize = 4;
  589. SetWindowSize();
  590. CheckMenuRadioItem(menu, IDM_X1, IDM_X4, IDM_X4, MF_BYCOMMAND);
  591. break;
  592. case IDM_HORIZONTAL:
  593. mmconfig->horizontal = MMCONFIG_HORIZONTAL;
  594. SetWindowSize();
  595. CheckMenuRadioItem(menu, IDM_HORIZONTAL, IDM_VERTICAL, IDM_HORIZONTAL, MF_BYCOMMAND);
  596. break;
  597. case IDM_VERTICAL:
  598. mmconfig->horizontal = MMCONFIG_VERTICAL;
  599. SetWindowSize();
  600. CheckMenuRadioItem(menu, IDM_HORIZONTAL, IDM_VERTICAL, IDM_VERTICAL, MF_BYCOMMAND);
  601. break;
  602. case IDM_PREFERENCE:
  603. OpenPreferenceDlg();
  604. break;
  605. default:
  606. handled = FALSE;
  607. }
  608. break;
  609. case WM_PAINT:
  610. if(wonw32ctx->running) {
  611. SendMessage(statusbar, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT("実行中"));
  612. } else {
  613. SendMessage(statusbar, SB_SETTEXT, (WPARAM)0, (LPARAM)TEXT(""));
  614. W32Display_DrawLCDWindow(hWnd, WonX_GetWonXDisplay());
  615. }
  616. handled = FALSE;
  617. break;
  618. case WM_SIZE:
  619. sbsize[0] = LOWORD(lParam) - 100;
  620. sbsize[1] = LOWORD(lParam);
  621. SendMessage(statusbar, SB_SETPARTS, 2, (LPARAM)sbsize);
  622. SendMessage(statusbar, WM_SIZE, wParam, lParam);
  623. SendMessage(statusbar, SB_SETTEXT, (WPARAM)1 | SBT_OWNERDRAW, (LPARAM)NULL);
  624. break;
  625. case WM_DRAWITEM:
  626. lpdi = (LPDRAWITEMSTRUCT)lParam;
  627. DrawIconEx(lpdi->hDC, lpdi->rcItem.left , lpdi->rcItem.top,
  628. lcdseg[LCD_SLEEP][mmvm->lcdseg & (1 << LCD_SLEEP) ? 1 : 0] , 16, 16, 0, NULL, DI_IMAGE);
  629. DrawIconEx(lpdi->hDC, lpdi->rcItem.left + 16, lpdi->rcItem.top,
  630. lcdseg[LCD_VERTICAL][mmvm->lcdseg & (1 << LCD_VERTICAL) ? 1 : 0], 16, 16, 0, NULL, DI_IMAGE);
  631. DrawIconEx(lpdi->hDC, lpdi->rcItem.left + 32, lpdi->rcItem.top,
  632. lcdseg[LCD_HORIZONTAL][mmvm->lcdseg & (1 << LCD_HORIZONTAL) ? 1 : 0], 16, 16, 0, NULL, DI_IMAGE);
  633. DrawIconEx(lpdi->hDC, lpdi->rcItem.left + 48, lpdi->rcItem.top,
  634. lcdseg[LCD_AUX1][mmvm->lcdseg & (1 << LCD_AUX1) ? 1 : 0], 16, 16, 0, NULL, DI_IMAGE);
  635. DrawIconEx(lpdi->hDC, lpdi->rcItem.left + 64, lpdi->rcItem.top,
  636. lcdseg[LCD_AUX2][mmvm->lcdseg & (1 << LCD_AUX2) ? 1 : 0], 16, 16, 0, NULL, DI_IMAGE);
  637. DrawIconEx(lpdi->hDC, lpdi->rcItem.left + 80, lpdi->rcItem.top,
  638. lcdseg[LCD_AUX3][mmvm->lcdseg & (1 << LCD_AUX3) ? 1 : 0], 16, 16, 0, NULL, DI_IMAGE);
  639. break;
  640. case WM_ENTERMENULOOP:
  641. if(wonw32ctx->running) {
  642. EnableMenuItem(menu, IDM_STOP, MF_BYCOMMAND | MF_ENABLED);
  643. } else {
  644. EnableMenuItem(menu, IDM_STOP, MF_BYCOMMAND | MF_GRAYED);
  645. }
  646. if(wonw32ctx->loaded) {
  647. EnableMenuItem(menu, IDM_RESTART, MF_BYCOMMAND | MF_ENABLED);
  648. } else {
  649. EnableMenuItem(menu, IDM_RESTART, MF_BYCOMMAND | MF_GRAYED);
  650. }
  651. break;
  652. case WM_DROPFILES:
  653. hdrop=(HDROP) wParam;
  654. DragQueryFile(hdrop, 0, drpfile, MAX_PATH);
  655. OpenAndRun(drpfile, TEXT(""));
  656. DragFinish(hdrop);
  657. break;
  658. case WM_NCACTIVATE:
  659. wonw32ctx->active = (BOOL) wParam;
  660. if(wonw32ctx->running) {
  661. if(wonw32ctx->active) {
  662. ResumeThread(wonw32ctx->cputhread);
  663. } else {
  664. #ifndef _DEBUG
  665. SuspendThread(wonw32ctx->cputhread);
  666. #endif
  667. }
  668. }
  669. handled = FALSE;
  670. break;
  671. case WM_CLOSE:
  672. PostQuitMessage( 0 );
  673. break;
  674. default:
  675. handled = FALSE;
  676. break;
  677. }
  678. if(handled)
  679. return FALSE;
  680. else
  681. return DefWindowProc( hWnd, message, wParam, lParam );
  682. }
  683. // バージョン情報ボックス用メッセージ ハンドラ
  684. LRESULT CALLBACK About( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
  685. {
  686. switch( message )
  687. {
  688. case WM_INITDIALOG:
  689. return TRUE;
  690. case WM_COMMAND:
  691. if( LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL )
  692. {
  693. EndDialog(hDlg, LOWORD(wParam));
  694. return TRUE;
  695. }
  696. break;
  697. }
  698. return FALSE;
  699. }
  700. // ライセンス情報ボックス用メッセージ ハンドラ
  701. LRESULT CALLBACK License( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
  702. {
  703. HRSRC rsc;
  704. LPCTSTR msg;
  705. HWND msgwnd;
  706. switch( message )
  707. {
  708. case WM_INITDIALOG:
  709. rsc = FindResource(NULL, MAKEINTRESOURCE(IDR_LICENSE), TEXT("TEXT"));
  710. msg = (LPCTSTR)LoadResource(NULL, rsc);
  711. msgwnd = GetDlgItem(hDlg, IDC_LICENSE);
  712. SetWindowText(msgwnd, msg);
  713. return TRUE;
  714. case WM_COMMAND:
  715. if( LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL )
  716. {
  717. EndDialog(hDlg, LOWORD(wParam));
  718. return TRUE;
  719. }
  720. break;
  721. }
  722. return FALSE;
  723. }
  724. static void W32Display_DrawLCDWindow(HWND hWnd, WonXDisplay display) {
  725. HDC hdc;
  726. RECT dr, sr;
  727. POINT p;
  728. if(!ddInit)
  729. return;
  730. p.x = p.y = 0;
  731. ClientToScreen(wonw32ctx->hWnd, &p);
  732. dr.left = p.x;
  733. dr.top = p.y;
  734. dr.right = dr.left + wonw32ctx->winwidth;
  735. dr.bottom = dr.top + wonw32ctx->winheight;
  736. sr.left = sr.top = 0;
  737. sr.right = wonw32ctx->ww_lcd_width;
  738. sr.bottom = wonw32ctx->ww_lcd_height;
  739. screen[0]->GetDC(&hdc);
  740. BitBlt(hdc, 0, 0, wonw32ctx->ww_lcd_width, wonw32ctx->ww_lcd_height, wonw32ctx->title, 0, 0, SRCCOPY);
  741. screen[0]->ReleaseDC(hdc);
  742. lpDDSPrimary->Blt(&dr, screen[0], &sr, DDBLT_WAIT, NULL);
  743. }
  744. static void DrawScreen(LPBYTE surfm, int screenno, LONG pitch) {
  745. int surfa;
  746. WWScreen screen = wonxobj->ww_screen[screenno];
  747. int plt[9];
  748. int *palette = &plt[1];
  749. int pixel;
  750. int x, y;
  751. int sx = 0, sy = 0, ex = 0, ey = 0;
  752. int mode = 0;
  753. int i;
  754. int rx, ry;
  755. BOOL enable;
  756. plt[0] = -1;
  757. WWColorMap_GetLCDColors(WWDisplay_GetColorMap(wonxobj->ww_display), plt + 1);
  758. if(screenno)
  759. mode = WWScreen_GetMode(screen);
  760. rx = WWScreen_GetRollX(screen);
  761. ry = WWScreen_GetRollY(screen);
  762. if ( (mode == WW_SCREEN_INSIDE_ONLY) || (mode == WW_SCREEN_OUTSIDE_ONLY) ) {
  763. sx = WWScreen_GetDrawX(screen);
  764. sy = WWScreen_GetDrawX(screen);
  765. ex = sx + WWScreen_GetDrawWidth( screen);
  766. ey = sy + WWScreen_GetDrawHeight(screen);
  767. }
  768. enable = WWScreen_GetEnable(screen);
  769. surfa = 0;
  770. if(mmconfig->horizontal) {
  771. for(y = 0; y < wonw32ctx->ww_lcd_height; y++) {
  772. surfa = y * pitch;
  773. for (x = 0; x < wonw32ctx->ww_lcd_width; x++) {
  774. pixel = enable ? WWScreen_GetPixel(screen, x + rx, y + ry) : -1;
  775. if (mode == WW_SCREEN_INSIDE_ONLY) {
  776. if( (x < sx) || (x > ex) || (y < sy) || (y > ey) ) {
  777. pixel = -1;
  778. }
  779. } else if (mode == WW_SCREEN_OUTSIDE_ONLY) {
  780. if ( (x >= sx) && (x <= ex) && (y >= sy) && (y <= ey) ) {
  781. pixel = -1;
  782. }
  783. }
  784. for(i = 3; i >= (4 - bytesPerPixel); i--) {
  785. surfm[surfa++] = ddclrs[palette[pixel] + 1][i];
  786. }
  787. }
  788. }
  789. } else {
  790. for(y = 0; y < wonw32ctx->ww_lcd_width; y++) {
  791. surfa = y * pitch;
  792. for (x = 0; x < wonw32ctx->ww_lcd_height; x++) {
  793. pixel = enable ? WWScreen_GetPixel(screen, (wonw32ctx->ww_lcd_width - y) + rx, x + ry) : -1;
  794. if (mode == WW_SCREEN_INSIDE_ONLY) {
  795. if( (x < sx) || (x > ex) || (y < sy) || (y > ey) ) {
  796. pixel = -1;
  797. }
  798. } else if (mode == WW_SCREEN_OUTSIDE_ONLY) {
  799. if ( (x >= sx) && (x <= ex) && (y >= sy) && (y <= ey) ) {
  800. pixel = -1;
  801. }
  802. }
  803. for(i = 3; i >= (4 - bytesPerPixel); i--) {
  804. surfm[surfa++] = ddclrs[palette[pixel] + 1][i];
  805. }
  806. }
  807. }
  808. }
  809. }
  810. static void DrawSprite(LPBYTE surfm, WWSprite sprite, LONG pitch) {
  811. int surfa;
  812. int x, y, lcd_x, lcd_y;
  813. int sx, sy, ex, ey;
  814. int pixel, outside;
  815. WWDisplay display = wonxobj->ww_display;
  816. int palette[8];
  817. int i;
  818. WWColorMap_GetLCDColors(WWDisplay_GetColorMap(display), palette);
  819. sx = WWDisplay_GetSpriteWindowX(display) - 1;
  820. sy = WWDisplay_GetSpriteWindowY(display) - 1;
  821. ex = sx + WWDisplay_GetSpriteWindowWidth(display);
  822. ey = sy + WWDisplay_GetSpriteWindowHeight(display);
  823. for (y = 0; y < 8; y++) {
  824. for (x = 0; x < 8; x++) {
  825. pixel = WWSprite_GetPixel(sprite, x, y);
  826. /* 透明色の場合 */
  827. if (pixel == -1) continue;
  828. lcd_x = WWSprite_GetX(sprite) + x;
  829. lcd_y = WWSprite_GetY(sprite) + y;
  830. if (WWDisplay_GetSpriteWindowEnable(display)) {
  831. if ( (lcd_x < sx) || (lcd_y < sy) || (lcd_x > ex) || (lcd_y > ey) )
  832. outside = 1;
  833. else
  834. outside = 0;
  835. if (WWSprite_GetClipping(sprite)) { /* ウインドウの外側部分を表示 */
  836. if (!outside) continue;
  837. } else { /* ウインドウの内側部分を表示 */
  838. if (outside) continue;
  839. }
  840. }
  841. if(mmconfig->horizontal)
  842. surfa = (lcd_x * bytesPerPixel) + (pitch * lcd_y);
  843. else
  844. surfa = (lcd_y * bytesPerPixel) + (pitch * (wonw32ctx->ww_lcd_width - lcd_x));
  845. for(i = 3; i >= (4 - bytesPerPixel); i--) {
  846. surfm[surfa++] = ddclrs[palette[pixel] + 1][i];
  847. }
  848. }
  849. }
  850. return;
  851. }
  852. #ifdef _DEBUG
  853. void ShowError(int code) {
  854. LPVOID lpMsgBuf;
  855. FormatMessage(
  856. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  857. FORMAT_MESSAGE_FROM_SYSTEM |
  858. FORMAT_MESSAGE_IGNORE_INSERTS,
  859. NULL,
  860. code,
  861. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // デフォルト言語
  862. (LPTSTR) &lpMsgBuf,
  863. 0,
  864. NULL
  865. );
  866. MessageBox( NULL, (LPTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
  867. LocalFree( lpMsgBuf );
  868. }
  869. #endif