Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / DX11ClothDemo / DXUT / Optional / DXUTgui.cpp
1 //--------------------------------------------------------------------------------------\r
2 // File: DXUTgui.cpp\r
3 //\r
4 // Copyright (c) Microsoft Corporation. All rights reserved.\r
5 //--------------------------------------------------------------------------------------\r
6 #include "DXUT.h"\r
7 #include "DXUTgui.h"\r
8 #include "DXUTsettingsDlg.h"\r
9 #include "DXUTres.h"\r
10 \r
11 #include "SDKMisc.h"\r
12 \r
13 #undef min // use __min instead\r
14 #undef max // use __max instead\r
15 \r
16 #ifndef WM_XBUTTONDOWN\r
17 #define WM_XBUTTONDOWN 0x020B // (not always defined)\r
18 #endif\r
19 #ifndef WM_XBUTTONUP\r
20 #define WM_XBUTTONUP 0x020C // (not always defined)\r
21 #endif\r
22 #ifndef WM_MOUSEWHEEL\r
23 #define WM_MOUSEWHEEL 0x020A // (not always defined)\r
24 #endif\r
25 #ifndef WHEEL_DELTA\r
26 #define WHEEL_DELTA 120 // (not always defined)\r
27 #endif\r
28 \r
29 // Minimum scroll bar thumb size\r
30 #define SCROLLBAR_MINTHUMBSIZE 8\r
31 \r
32 // Delay and repeat period when clicking on the scroll bar arrows\r
33 #define SCROLLBAR_ARROWCLICK_DELAY  0.33\r
34 #define SCROLLBAR_ARROWCLICK_REPEAT 0.05\r
35 \r
36 #define DXUT_NEAR_BUTTON_DEPTH 0.6f\r
37 #define DXUT_FAR_BUTTON_DEPTH 0.8f\r
38 \r
39 #define DXUT_MAX_GUI_SPRITES 500\r
40 \r
41 D3DCOLORVALUE D3DCOLOR_TO_D3DCOLORVALUE( D3DCOLOR c )\r
42 {\r
43     D3DCOLORVALUE cv =\r
44     {\r
45         ( ( c >> 16 ) & 0xFF ) / 255.0f,\r
46         ( ( c >> 8 ) & 0xFF ) / 255.0f,\r
47         ( c & 0xFF ) / 255.0f,\r
48         ( ( c >> 24 ) & 0xFF ) / 255.0f\r
49     };\r
50     return cv;\r
51 }\r
52 \r
53 #define UNISCRIBE_DLLNAME L"usp10.dll"\r
54 \r
55 #define GETPROCADDRESS( Module, APIName, Temp ) \\r
56     Temp = GetProcAddress( Module, #APIName ); \\r
57     if( Temp ) \\r
58         *(FARPROC*)&_##APIName = Temp\r
59 \r
60 #define PLACEHOLDERPROC( APIName ) \\r
61     _##APIName = Dummy_##APIName\r
62 \r
63 #define IMM32_DLLNAME L"imm32.dll"\r
64 #define VER_DLLNAME L"version.dll"\r
65 \r
66 CHAR g_strUIEffectFile[] = \\r
67     "Texture2D g_Texture;"\\r
68     ""\\r
69     "SamplerState Sampler"\\r
70     "{"\\r
71     "    Filter = MIN_MAG_MIP_LINEAR;"\\r
72     "    AddressU = Wrap;"\\r
73     "    AddressV = Wrap;"\\r
74     "};"\\r
75     ""\\r
76     "BlendState UIBlend"\\r
77     "{"\\r
78     "    AlphaToCoverageEnable = FALSE;"\\r
79     "    BlendEnable[0] = TRUE;"\\r
80     "    SrcBlend = SRC_ALPHA;"\\r
81     "    DestBlend = INV_SRC_ALPHA;"\\r
82     "    BlendOp = ADD;"\\r
83     "    SrcBlendAlpha = ONE;"\\r
84     "    DestBlendAlpha = ZERO;"\\r
85     "    BlendOpAlpha = ADD;"\\r
86     "    RenderTargetWriteMask[0] = 0x0F;"\\r
87     "};"\\r
88     ""\\r
89     "BlendState NoBlending"\\r
90     "{"\\r
91     "    BlendEnable[0] = FALSE;"\\r
92     "    RenderTargetWriteMask[0] = 0x0F;"\\r
93     "};"\\r
94     ""\\r
95     "DepthStencilState DisableDepth"\\r
96     "{"\\r
97     "    DepthEnable = false;"\\r
98     "};"\\r
99     "DepthStencilState EnableDepth"\\r
100     "{"\\r
101     "    DepthEnable = true;"\\r
102     "};"\\r
103     "struct VS_OUTPUT"\\r
104     "{"\\r
105     "    float4 Pos : POSITION;"\\r
106     "    float4 Dif : COLOR;"\\r
107     "    float2 Tex : TEXCOORD;"\\r
108     "};"\\r
109     ""\\r
110     "VS_OUTPUT VS( float3 vPos : POSITION,"\\r
111     "              float4 Dif : COLOR,"\\r
112     "              float2 vTexCoord0 : TEXCOORD )"\\r
113     "{"\\r
114     "    VS_OUTPUT Output;"\\r
115     ""\\r
116     "    Output.Pos = float4( vPos, 1.0f );"\\r
117     "    Output.Dif = Dif;"\\r
118     "    Output.Tex = vTexCoord0;"\\r
119     ""\\r
120     "    return Output;"\\r
121     "}"\\r
122     ""\\r
123     "float4 PS( VS_OUTPUT In ) : SV_Target"\\r
124     "{"\\r
125     "    return g_Texture.Sample( Sampler, In.Tex ) * In.Dif;"\\r
126     "}"\\r
127     ""\\r
128     "float4 PSUntex( VS_OUTPUT In ) : SV_Target"\\r
129     "{"\\r
130     "    return In.Dif;"\\r
131     "}"\\r
132     ""\\r
133     "technique10 RenderUI"\\r
134     "{"\\r
135     "    pass P0"\\r
136     "    {"\\r
137     "        SetVertexShader( CompileShader( vs_4_0, VS() ) );"\\r
138     "        SetGeometryShader( NULL );"\\r
139     "        SetPixelShader( CompileShader( ps_4_0, PS() ) );"\\r
140     "        SetDepthStencilState( DisableDepth, 0 );"\\r
141     "        SetBlendState( UIBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );"\\r
142     "    }"\\r
143     "}"\\r
144     "technique10 RenderUIUntex"\\r
145     "{"\\r
146     "    pass P0"\\r
147     "    {"\\r
148     "        SetVertexShader( CompileShader( vs_4_0, VS() ) );"\\r
149     "        SetGeometryShader( NULL );"\\r
150     "        SetPixelShader( CompileShader( ps_4_0, PSUntex() ) );"\\r
151     "        SetDepthStencilState( DisableDepth, 0 );"\\r
152     "        SetBlendState( UIBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );"\\r
153     "    }"\\r
154     "}"\\r
155     "technique10 RestoreState"\\r
156     "{"\\r
157     "    pass P0"\\r
158     "    {"\\r
159     "        SetDepthStencilState( EnableDepth, 0 );"\\r
160     "        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );"\\r
161     "    }"\\r
162     "}";\r
163 const UINT              g_uUIEffectFileSize = sizeof( g_strUIEffectFile );\r
164 \r
165 \r
166 // DXUT_MAX_EDITBOXLENGTH is the maximum string length allowed in edit boxes,\r
167 // including the NULL terminator.\r
168 // \r
169 // Uniscribe does not support strings having bigger-than-16-bits length.\r
170 // This means that the string must be less than 65536 characters long,\r
171 // including the NULL terminator.\r
172 #define DXUT_MAX_EDITBOXLENGTH 0xFFFF\r
173 \r
174 \r
175 double                  CDXUTDialog::s_fTimeRefresh = 0.0f;\r
176 CDXUTControl*           CDXUTDialog::s_pControlFocus = NULL;        // The control which has focus\r
177 CDXUTControl*           CDXUTDialog::s_pControlPressed = NULL;      // The control currently pressed\r
178 \r
179 \r
180 struct DXUT_SCREEN_VERTEX\r
181 {\r
182     float x, y, z, h;\r
183     D3DCOLOR color;\r
184     float tu, tv;\r
185 \r
186     static DWORD FVF;\r
187 };\r
188 DWORD                   DXUT_SCREEN_VERTEX::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1;\r
189 \r
190 \r
191 struct DXUT_SCREEN_VERTEX_UNTEX\r
192 {\r
193     float x, y, z, h;\r
194     D3DCOLOR color;\r
195 \r
196     static DWORD FVF;\r
197 };\r
198 DWORD                   DXUT_SCREEN_VERTEX_UNTEX::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;\r
199 \r
200 \r
201 struct DXUT_SCREEN_VERTEX_10\r
202 {\r
203     float x, y, z;\r
204     D3DCOLORVALUE color;\r
205     float tu, tv;\r
206 };\r
207 \r
208 \r
209 inline int RectWidth( RECT& rc )\r
210 {\r
211     return ( ( rc ).right - ( rc ).left );\r
212 }\r
213 inline int RectHeight( RECT& rc )\r
214 {\r
215     return ( ( rc ).bottom - ( rc ).top );\r
216 }\r
217 \r
218 \r
219 HRESULT InitFont11( ID3D11Device* pd3d11Device, ID3D11InputLayout* pInputLayout );\r
220 void EndFont11();\r
221 \r
222 //--------------------------------------------------------------------------------------\r
223 // CDXUTDialog class\r
224 //--------------------------------------------------------------------------------------\r
225 \r
226 //--------------------------------------------------------------------------------------\r
227 CDXUTDialog::CDXUTDialog()\r
228 {\r
229     m_x = 0;\r
230     m_y = 0;\r
231     m_width = 0;\r
232     m_height = 0;\r
233 \r
234     m_pManager = NULL;\r
235     m_bVisible = true;\r
236     m_bCaption = false;\r
237     m_bMinimized = false;\r
238     m_bDrag = false;\r
239     m_wszCaption[0] = L'\0';\r
240     m_nCaptionHeight = 18;\r
241 \r
242     m_colorTopLeft = 0;\r
243     m_colorTopRight = 0;\r
244     m_colorBottomLeft = 0;\r
245     m_colorBottomRight = 0;\r
246 \r
247     m_pCallbackEvent = NULL;\r
248     m_pCallbackEventUserContext = NULL;\r
249 \r
250     m_fTimeLastRefresh = 0;\r
251 \r
252     m_pControlMouseOver = NULL;\r
253 \r
254     m_pNextDialog = this;\r
255     m_pPrevDialog = this;\r
256 \r
257     m_nDefaultControlID = 0xffff;\r
258     m_bNonUserEvents = false;\r
259     m_bKeyboardInput = false;\r
260     m_bMouseInput = true;\r
261 }\r
262 \r
263 \r
264 //--------------------------------------------------------------------------------------\r
265 CDXUTDialog::~CDXUTDialog()\r
266 {\r
267     int i = 0;\r
268 \r
269     RemoveAllControls();\r
270 \r
271     m_Fonts.RemoveAll();\r
272     m_Textures.RemoveAll();\r
273 \r
274     for( i = 0; i < m_DefaultElements.GetSize(); i++ )\r
275     {\r
276         DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i );\r
277         SAFE_DELETE( pElementHolder );\r
278     }\r
279 \r
280     m_DefaultElements.RemoveAll();\r
281 }\r
282 \r
283 \r
284 //--------------------------------------------------------------------------------------\r
285 void CDXUTDialog::Init( CDXUTDialogResourceManager* pManager, bool bRegisterDialog )\r
286 {\r
287     m_pManager = pManager;\r
288     if( bRegisterDialog )\r
289         pManager->RegisterDialog( this );\r
290 \r
291     SetTexture( 0, MAKEINTRESOURCE( 0xFFFF ), ( HMODULE )0xFFFF );\r
292     InitDefaultElements();\r
293 }\r
294 \r
295 \r
296 //--------------------------------------------------------------------------------------\r
297 void CDXUTDialog::Init( CDXUTDialogResourceManager* pManager, bool bRegisterDialog, LPCWSTR pszControlTextureFilename )\r
298 {\r
299     m_pManager = pManager;\r
300     if( bRegisterDialog )\r
301         pManager->RegisterDialog( this );\r
302     SetTexture( 0, pszControlTextureFilename );\r
303     InitDefaultElements();\r
304 }\r
305 \r
306 \r
307 //--------------------------------------------------------------------------------------\r
308 void CDXUTDialog::Init( CDXUTDialogResourceManager* pManager, bool bRegisterDialog,\r
309                         LPCWSTR szControlTextureResourceName, HMODULE hControlTextureResourceModule )\r
310 {\r
311     m_pManager = pManager;\r
312     if( bRegisterDialog )\r
313         pManager->RegisterDialog( this );\r
314 \r
315     SetTexture( 0, szControlTextureResourceName, hControlTextureResourceModule );\r
316     InitDefaultElements();\r
317 }\r
318 \r
319 \r
320 //--------------------------------------------------------------------------------------\r
321 void CDXUTDialog::SetCallback( PCALLBACKDXUTGUIEVENT pCallback, void* pUserContext )\r
322 {\r
323     // If this assert triggers, you need to call CDXUTDialog::Init() first.  This change\r
324     // was made so that the DXUT's GUI could become seperate and optional from DXUT's core.  The \r
325     // creation and interfacing with CDXUTDialogResourceManager is now the responsibility \r
326     // of the application if it wishes to use DXUT's GUI.\r
327     assert( m_pManager != NULL && L"To fix call CDXUTDialog::Init() first.  See comments for details." );\r
328 \r
329     m_pCallbackEvent = pCallback;\r
330     m_pCallbackEventUserContext = pUserContext;\r
331 }\r
332 \r
333 \r
334 //--------------------------------------------------------------------------------------\r
335 void CDXUTDialog::RemoveControl( int ID )\r
336 {\r
337     for( int i = 0; i < m_Controls.GetSize(); i++ )\r
338     {\r
339         CDXUTControl* pControl = m_Controls.GetAt( i );\r
340         if( pControl->GetID() == ID )\r
341         {\r
342             // Clean focus first\r
343             ClearFocus();\r
344 \r
345             // Clear references to this control\r
346             if( s_pControlFocus == pControl )\r
347                 s_pControlFocus = NULL;\r
348             if( s_pControlPressed == pControl )\r
349                 s_pControlPressed = NULL;\r
350             if( m_pControlMouseOver == pControl )\r
351                 m_pControlMouseOver = NULL;\r
352 \r
353             SAFE_DELETE( pControl );\r
354             m_Controls.Remove( i );\r
355 \r
356             return;\r
357         }\r
358     }\r
359 }\r
360 \r
361 \r
362 //--------------------------------------------------------------------------------------\r
363 void CDXUTDialog::RemoveAllControls()\r
364 {\r
365     if( s_pControlFocus && s_pControlFocus->m_pDialog == this )\r
366         s_pControlFocus = NULL;\r
367     if( s_pControlPressed && s_pControlPressed->m_pDialog == this )\r
368         s_pControlPressed = NULL;\r
369     m_pControlMouseOver = NULL;\r
370 \r
371     for( int i = 0; i < m_Controls.GetSize(); i++ )\r
372     {\r
373         CDXUTControl* pControl = m_Controls.GetAt( i );\r
374         SAFE_DELETE( pControl );\r
375     }\r
376 \r
377     m_Controls.RemoveAll();\r
378 }\r
379 \r
380 \r
381 //--------------------------------------------------------------------------------------\r
382 CDXUTDialogResourceManager::CDXUTDialogResourceManager()\r
383 {\r
384     // Begin D3D9-specific\r
385     m_pd3d9Device = NULL;\r
386     m_pStateBlock = NULL;\r
387     m_pSprite = NULL;\r
388 \r
389     // Begin D3D11-specific\r
390     // Shaders\r
391     m_pVSRenderUI11 = NULL;\r
392     m_pPSRenderUI11 = NULL;\r
393     m_pPSRenderUIUntex11 = NULL;\r
394 \r
395     // States\r
396     m_pDepthStencilStateUI11 = NULL;\r
397     m_pRasterizerStateUI11 = NULL;\r
398     m_pBlendStateUI11 = NULL;\r
399     m_pSamplerStateUI11 = NULL;\r
400     m_pDepthStencilStateStored11 = NULL;\r
401     m_pRasterizerStateStored11 = NULL;\r
402     m_pBlendStateStored11 = NULL;\r
403     m_pSamplerStateStored11 = NULL;\r
404 \r
405     m_pInputLayout11 = NULL;\r
406     m_pVBScreenQuad11 = NULL;\r
407     m_pSpriteBuffer11 = NULL;\r
408 }\r
409 \r
410 \r
411 //--------------------------------------------------------------------------------------\r
412 CDXUTDialogResourceManager::~CDXUTDialogResourceManager()\r
413 {\r
414     int i;\r
415     for( i = 0; i < m_FontCache.GetSize(); i++ )\r
416     {\r
417         DXUTFontNode* pFontNode = m_FontCache.GetAt( i );\r
418         SAFE_DELETE( pFontNode );\r
419     }\r
420     m_FontCache.RemoveAll();\r
421 \r
422     for( i = 0; i < m_TextureCache.GetSize(); i++ )\r
423     {\r
424         DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i );\r
425         SAFE_DELETE( pTextureNode );\r
426     }\r
427     m_TextureCache.RemoveAll();\r
428 \r
429     CUniBuffer::Uninitialize();\r
430 }\r
431 \r
432 \r
433 //--------------------------------------------------------------------------------------\r
434 HRESULT CDXUTDialogResourceManager::OnD3D9CreateDevice( LPDIRECT3DDEVICE9 pd3dDevice )\r
435 {\r
436     HRESULT hr = S_OK;\r
437     int i = 0;\r
438 \r
439     m_pd3d9Device = pd3dDevice;\r
440 \r
441     for( i = 0; i < m_FontCache.GetSize(); i++ )\r
442     {\r
443         hr = CreateFont9( i );\r
444         if( FAILED( hr ) )\r
445             return hr;\r
446     }\r
447 \r
448     for( i = 0; i < m_TextureCache.GetSize(); i++ )\r
449     {\r
450         hr = CreateTexture9( i );\r
451         if( FAILED( hr ) )\r
452             return hr;\r
453     }\r
454 \r
455     hr = D3DXCreateSprite( pd3dDevice, &m_pSprite );\r
456     if( FAILED( hr ) )\r
457         return DXUT_ERR( L"D3DXCreateSprite", hr );\r
458 \r
459     return S_OK;\r
460 }\r
461 \r
462 \r
463 //--------------------------------------------------------------------------------------\r
464 HRESULT CDXUTDialogResourceManager::OnD3D9ResetDevice()\r
465 {\r
466     HRESULT hr = S_OK;\r
467 \r
468     for( int i = 0; i < m_FontCache.GetSize(); i++ )\r
469     {\r
470         DXUTFontNode* pFontNode = m_FontCache.GetAt( i );\r
471 \r
472         if( pFontNode->pFont9 )\r
473             pFontNode->pFont9->OnResetDevice();\r
474     }\r
475 \r
476     if( m_pSprite )\r
477         m_pSprite->OnResetDevice();\r
478 \r
479     V_RETURN( m_pd3d9Device->CreateStateBlock( D3DSBT_ALL, &m_pStateBlock ) );\r
480 \r
481     return S_OK;\r
482 }\r
483 \r
484 //--------------------------------------------------------------------------------------\r
485 bool CDXUTDialogResourceManager::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )\r
486 {\r
487     return false;\r
488 }\r
489 \r
490 \r
491 //--------------------------------------------------------------------------------------\r
492 void CDXUTDialogResourceManager::OnD3D9LostDevice()\r
493 {\r
494     for( int i = 0; i < m_FontCache.GetSize(); i++ )\r
495     {\r
496         DXUTFontNode* pFontNode = m_FontCache.GetAt( i );\r
497 \r
498         if( pFontNode->pFont9 )\r
499             pFontNode->pFont9->OnLostDevice();\r
500     }\r
501 \r
502     if( m_pSprite )\r
503         m_pSprite->OnLostDevice();\r
504 \r
505     SAFE_RELEASE( m_pStateBlock );\r
506 }\r
507 \r
508 \r
509 //--------------------------------------------------------------------------------------\r
510 void CDXUTDialogResourceManager::OnD3D9DestroyDevice()\r
511 {\r
512     int i = 0;\r
513 \r
514     m_pd3d9Device = NULL;\r
515 \r
516     // Release the resources but don't clear the cache, as these will need to be\r
517     // recreated if the device is recreated\r
518     for( i = 0; i < m_FontCache.GetSize(); i++ )\r
519     {\r
520         DXUTFontNode* pFontNode = m_FontCache.GetAt( i );\r
521         SAFE_RELEASE( pFontNode->pFont9 );\r
522     }\r
523 \r
524     for( i = 0; i < m_TextureCache.GetSize(); i++ )\r
525     {\r
526         DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i );\r
527         SAFE_RELEASE( pTextureNode->pTexture9 );\r
528     }\r
529 \r
530     SAFE_RELEASE( m_pSprite );\r
531 }\r
532 \r
533 \r
534 \r
535 HRESULT CDXUTDialogResourceManager::OnD3D11CreateDevice( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext )\r
536 {\r
537     m_pd3d11Device = pd3dDevice;\r
538     m_pd3d11DeviceContext = pd3d11DeviceContext;\r
539 \r
540     HRESULT hr = S_OK;\r
541 \r
542     // Compile Shaders\r
543     ID3DBlob* pVSBlob = NULL;\r
544     ID3DBlob* pPSBlob = NULL;\r
545     ID3DBlob* pPSUntexBlob = NULL;\r
546     V_RETURN( D3DCompile( g_strUIEffectFile, g_uUIEffectFileSize, "none", NULL, NULL, "VS", "vs_4_0_level_9_1", \r
547          D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY, 0, &pVSBlob, NULL ) );\r
548     V_RETURN( D3DCompile( g_strUIEffectFile, g_uUIEffectFileSize, "none", NULL, NULL, "PS", "ps_4_0_level_9_1", \r
549          D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY, 0, &pPSBlob, NULL ) );\r
550     V_RETURN( D3DCompile( g_strUIEffectFile, g_uUIEffectFileSize, "none", NULL, NULL, "PSUntex", "ps_4_0_level_9_1", \r
551          D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY, 0, &pPSUntexBlob, NULL ) );\r
552 //D3D10_SHADER_ENABLE_STRICTNESS\r
553 \r
554     // Create Shaders\r
555     V_RETURN( pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_pVSRenderUI11 ) );\r
556     V_RETURN( pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &m_pPSRenderUI11 ) );\r
557     V_RETURN( pd3dDevice->CreatePixelShader( pPSUntexBlob->GetBufferPointer(), pPSUntexBlob->GetBufferSize(), NULL, &m_pPSRenderUIUntex11 ) );\r
558 \r
559     // States\r
560     D3D11_DEPTH_STENCIL_DESC DSDesc;\r
561     ZeroMemory( &DSDesc, sizeof( D3D11_DEPTH_STENCIL_DESC ) );\r
562     DSDesc.DepthEnable = FALSE;\r
563     DSDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;\r
564     DSDesc.DepthFunc = D3D11_COMPARISON_LESS;\r
565     DSDesc.StencilEnable = FALSE;\r
566     V_RETURN( pd3dDevice->CreateDepthStencilState( &DSDesc, &m_pDepthStencilStateUI11 ) );\r
567 \r
568     D3D11_RASTERIZER_DESC RSDesc;\r
569     RSDesc.AntialiasedLineEnable = FALSE;\r
570     RSDesc.CullMode = D3D11_CULL_BACK;\r
571     RSDesc.DepthBias = 0;\r
572     RSDesc.DepthBiasClamp = 0.0f;\r
573     RSDesc.DepthClipEnable = TRUE;\r
574     RSDesc.FillMode = D3D11_FILL_SOLID;\r
575     RSDesc.FrontCounterClockwise = FALSE;\r
576     RSDesc.MultisampleEnable = TRUE;\r
577     RSDesc.ScissorEnable = FALSE;\r
578     RSDesc.SlopeScaledDepthBias = 0.0f;\r
579     V_RETURN( pd3dDevice->CreateRasterizerState( &RSDesc, &m_pRasterizerStateUI11 ) );\r
580 \r
581     D3D11_BLEND_DESC BSDesc;\r
582     ZeroMemory( &BSDesc, sizeof( D3D11_BLEND_DESC ) );\r
583     \r
584     BSDesc.RenderTarget[0].BlendEnable = TRUE;\r
585     BSDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;\r
586     BSDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;\r
587     BSDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;\r
588     BSDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;\r
589     BSDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;\r
590     BSDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;\r
591     BSDesc.RenderTarget[0].RenderTargetWriteMask = 0x0F;\r
592 \r
593     V_RETURN( pd3dDevice->CreateBlendState( &BSDesc, &m_pBlendStateUI11 ) );\r
594 \r
595     D3D11_SAMPLER_DESC SSDesc;\r
596     ZeroMemory( &SSDesc, sizeof( D3D11_SAMPLER_DESC ) );\r
597     SSDesc.Filter = D3D11_FILTER_ANISOTROPIC   ;\r
598     SSDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;\r
599     SSDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;\r
600     SSDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;\r
601     SSDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;\r
602     SSDesc.MaxAnisotropy = 16;\r
603     SSDesc.MinLOD = 0;\r
604     SSDesc.MaxLOD = D3D11_FLOAT32_MAX;\r
605     if ( pd3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3 ) {\r
606         SSDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;\r
607         SSDesc.MaxAnisotropy = 0;\r
608     }\r
609     V_RETURN( pd3dDevice->CreateSamplerState( &SSDesc, &m_pSamplerStateUI11 ) );\r
610 \r
611     // Create the font and texture objects in the cache arrays.\r
612     int i = 0;\r
613     for( i = 0; i < m_FontCache.GetSize(); i++ )\r
614     {\r
615         hr = CreateFont11( i );\r
616         if( FAILED( hr ) )\r
617             return hr;\r
618     }\r
619 \r
620     for( i = 0; i < m_TextureCache.GetSize(); i++ )\r
621     {\r
622         hr = CreateTexture11( i );\r
623         if( FAILED( hr ) )\r
624             return hr;\r
625     }\r
626 \r
627     // Create input layout\r
628     const D3D11_INPUT_ELEMENT_DESC layout[] =\r
629         {\r
630             { "POSITION",  0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },\r
631             { "COLOR",     0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },\r
632             { "TEXCOORD",  0, DXGI_FORMAT_R32G32_FLOAT,       0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },\r
633         };\r
634 \r
635     V_RETURN( pd3dDevice->CreateInputLayout( layout, ARRAYSIZE( layout ), pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &m_pInputLayout11 ) );\r
636 \r
637     // Release the blobs\r
638     SAFE_RELEASE( pVSBlob );\r
639     SAFE_RELEASE( pPSBlob );\r
640     SAFE_RELEASE( pPSUntexBlob );\r
641 \r
642     // Create a vertex buffer quad for rendering later\r
643     D3D11_BUFFER_DESC BufDesc;\r
644     BufDesc.ByteWidth = sizeof( DXUT_SCREEN_VERTEX_10 ) * 4;\r
645     BufDesc.Usage = D3D11_USAGE_DYNAMIC;\r
646     BufDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;\r
647     BufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;\r
648     BufDesc.MiscFlags = 0;\r
649     V_RETURN( pd3dDevice->CreateBuffer( &BufDesc, NULL, &m_pVBScreenQuad11 ) );\r
650 \r
651     // Init the D3D11 font\r
652     InitFont11( pd3dDevice, m_pInputLayout11 );\r
653 \r
654     return S_OK;\r
655 }\r
656 \r
657 \r
658 //--------------------------------------------------------------------------------------\r
659 HRESULT CDXUTDialogResourceManager::OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice,\r
660                                                              const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc )\r
661 {\r
662     HRESULT hr = S_OK;\r
663 \r
664     m_nBackBufferWidth = pBackBufferSurfaceDesc->Width;\r
665     m_nBackBufferHeight = pBackBufferSurfaceDesc->Height;\r
666 \r
667     return hr;\r
668 }\r
669 \r
670 \r
671 //--------------------------------------------------------------------------------------\r
672 void CDXUTDialogResourceManager::OnD3D11ReleasingSwapChain()\r
673 {\r
674 }\r
675 \r
676 \r
677 //--------------------------------------------------------------------------------------\r
678 void CDXUTDialogResourceManager::OnD3D11DestroyDevice()\r
679 {\r
680     int i;\r
681 \r
682     // Release the resources but don't clear the cache, as these will need to be\r
683     // recreated if the device is recreated\r
684 \r
685     for( i = 0; i < m_TextureCache.GetSize(); i++ )\r
686     {\r
687         DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i );\r
688         SAFE_RELEASE( pTextureNode->pTexResView11 );\r
689         SAFE_RELEASE( pTextureNode->pTexture11 );\r
690     }\r
691 \r
692     // D3D11\r
693     SAFE_RELEASE( m_pVBScreenQuad11 );\r
694     SAFE_RELEASE( m_pSpriteBuffer11 );\r
695     m_SpriteBufferBytes11 = 0;\r
696     SAFE_RELEASE( m_pInputLayout11 );\r
697 \r
698     // Shaders\r
699     SAFE_RELEASE( m_pVSRenderUI11 );\r
700     SAFE_RELEASE( m_pPSRenderUI11 );\r
701     SAFE_RELEASE( m_pPSRenderUIUntex11 );\r
702 \r
703     // States\r
704     SAFE_RELEASE( m_pDepthStencilStateUI11 );\r
705     SAFE_RELEASE( m_pRasterizerStateUI11 );\r
706     SAFE_RELEASE( m_pBlendStateUI11 );\r
707     SAFE_RELEASE( m_pSamplerStateUI11 );\r
708 \r
709     SAFE_RELEASE( m_pDepthStencilStateStored11 );\r
710     SAFE_RELEASE( m_pRasterizerStateStored11 );\r
711     SAFE_RELEASE( m_pBlendStateStored11 );\r
712     SAFE_RELEASE( m_pSamplerStateStored11 );\r
713 \r
714     EndFont11();\r
715 }\r
716 \r
717 //--------------------------------------------------------------------------------------\r
718 void CDXUTDialogResourceManager::StoreD3D11State( ID3D11DeviceContext* pd3dImmediateContext )\r
719 {\r
720     pd3dImmediateContext->OMGetDepthStencilState( &m_pDepthStencilStateStored11, &m_StencilRefStored11 );\r
721     pd3dImmediateContext->RSGetState( &m_pRasterizerStateStored11 );\r
722     pd3dImmediateContext->OMGetBlendState( &m_pBlendStateStored11, m_BlendFactorStored11, &m_SampleMaskStored11 );\r
723     pd3dImmediateContext->PSGetSamplers( 0, 1, &m_pSamplerStateStored11 );\r
724 }\r
725 \r
726 //--------------------------------------------------------------------------------------\r
727 void CDXUTDialogResourceManager::RestoreD3D11State( ID3D11DeviceContext* pd3dImmediateContext )\r
728 {\r
729     pd3dImmediateContext->OMSetDepthStencilState( m_pDepthStencilStateStored11, m_StencilRefStored11 );\r
730     pd3dImmediateContext->RSSetState( m_pRasterizerStateStored11 );\r
731     pd3dImmediateContext->OMSetBlendState( m_pBlendStateStored11, m_BlendFactorStored11, m_SampleMaskStored11 );\r
732     pd3dImmediateContext->PSSetSamplers( 0, 1, &m_pSamplerStateStored11 );\r
733 \r
734     SAFE_RELEASE( m_pDepthStencilStateStored11 );\r
735     SAFE_RELEASE( m_pRasterizerStateStored11 );\r
736     SAFE_RELEASE( m_pBlendStateStored11 );\r
737     SAFE_RELEASE( m_pSamplerStateStored11 );\r
738 }\r
739 \r
740 //--------------------------------------------------------------------------------------\r
741 void CDXUTDialogResourceManager::ApplyRenderUI11( ID3D11DeviceContext* pd3dImmediateContext )\r
742 {\r
743     // Shaders\r
744     pd3dImmediateContext->VSSetShader( m_pVSRenderUI11, NULL, 0 );\r
745     pd3dImmediateContext->HSSetShader( NULL, NULL, 0 );\r
746     pd3dImmediateContext->DSSetShader( NULL, NULL, 0 );\r
747     pd3dImmediateContext->GSSetShader( NULL, NULL, 0 );\r
748     pd3dImmediateContext->PSSetShader( m_pPSRenderUI11, NULL, 0 );\r
749 \r
750     // States\r
751     pd3dImmediateContext->OMSetDepthStencilState( m_pDepthStencilStateUI11, 0 );\r
752     pd3dImmediateContext->RSSetState( m_pRasterizerStateUI11 );\r
753     float BlendFactor[4] = { 0, 0, 0, 0 };\r
754     pd3dImmediateContext->OMSetBlendState( m_pBlendStateUI11, BlendFactor, 0xFFFFFFFF );\r
755     pd3dImmediateContext->PSSetSamplers( 0, 1, &m_pSamplerStateUI11 );\r
756 }\r
757 \r
758 //--------------------------------------------------------------------------------------\r
759 void CDXUTDialogResourceManager::ApplyRenderUIUntex11( ID3D11DeviceContext* pd3dImmediateContext )\r
760 {\r
761     // Shaders\r
762     pd3dImmediateContext->VSSetShader( m_pVSRenderUI11, NULL, 0 );\r
763     pd3dImmediateContext->HSSetShader( NULL, NULL, 0 );\r
764     pd3dImmediateContext->DSSetShader( NULL, NULL, 0 );\r
765     pd3dImmediateContext->GSSetShader( NULL, NULL, 0 );\r
766     pd3dImmediateContext->PSSetShader( m_pPSRenderUIUntex11, NULL, 0 );\r
767 \r
768     // States\r
769     pd3dImmediateContext->OMSetDepthStencilState( m_pDepthStencilStateUI11, 0 );\r
770     pd3dImmediateContext->RSSetState( m_pRasterizerStateUI11 );\r
771     float BlendFactor[4] = { 0, 0, 0, 0 };\r
772     pd3dImmediateContext->OMSetBlendState( m_pBlendStateUI11, BlendFactor, 0xFFFFFFFF );\r
773     pd3dImmediateContext->PSSetSamplers( 0, 1, &m_pSamplerStateUI11 );\r
774 }\r
775 \r
776 //--------------------------------------------------------------------------------------\r
777 void CDXUTDialogResourceManager::BeginSprites11( )\r
778 {\r
779     m_SpriteVertices.Reset();\r
780 }\r
781 \r
782 //--------------------------------------------------------------------------------------\r
783 void CDXUTDialogResourceManager::EndSprites11( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext )\r
784 {\r
785 \r
786     // ensure our buffer size can hold our sprites\r
787     UINT SpriteDataBytes = m_SpriteVertices.GetSize() * sizeof( DXUTSpriteVertex );\r
788     if( m_SpriteBufferBytes11 < SpriteDataBytes )\r
789     {\r
790         SAFE_RELEASE( m_pSpriteBuffer11 );\r
791         m_SpriteBufferBytes11 = SpriteDataBytes;\r
792 \r
793         D3D11_BUFFER_DESC BufferDesc;\r
794         BufferDesc.ByteWidth = m_SpriteBufferBytes11;\r
795         BufferDesc.Usage = D3D11_USAGE_DYNAMIC;\r
796         BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;\r
797         BufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;\r
798         BufferDesc.MiscFlags = 0;\r
799 \r
800         pd3dDevice->CreateBuffer( &BufferDesc, NULL, &m_pSpriteBuffer11 );\r
801     }\r
802 \r
803     // Copy the sprites over\r
804     D3D11_BOX destRegion;\r
805     destRegion.left = 0;\r
806     destRegion.right = SpriteDataBytes;\r
807     destRegion.top = 0;\r
808     destRegion.bottom = 1;\r
809     destRegion.front = 0;\r
810     destRegion.back = 1;\r
811     D3D11_MAPPED_SUBRESOURCE MappedResource;\r
812     if ( S_OK == pd3dImmediateContext->Map( m_pSpriteBuffer11, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ) { \r
813         CopyMemory( MappedResource.pData, (void*)m_SpriteVertices.GetData(), SpriteDataBytes );\r
814         pd3dImmediateContext->Unmap(m_pSpriteBuffer11, 0);\r
815     }\r
816 \r
817     // Draw\r
818     UINT Stride = sizeof( DXUTSpriteVertex );\r
819     UINT Offset = 0;\r
820     pd3dImmediateContext->IASetVertexBuffers( 0, 1, &m_pSpriteBuffer11, &Stride, &Offset );\r
821     pd3dImmediateContext->IASetInputLayout( m_pInputLayout11 );\r
822     pd3dImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );\r
823     pd3dImmediateContext->Draw( m_SpriteVertices.GetSize(), 0 );\r
824 \r
825     m_SpriteVertices.Reset();\r
826 }\r
827 \r
828 //--------------------------------------------------------------------------------------\r
829 bool CDXUTDialogResourceManager::RegisterDialog( CDXUTDialog* pDialog )\r
830 {\r
831     // Check that the dialog isn't already registered.\r
832     for( int i = 0; i < m_Dialogs.GetSize(); ++i )\r
833         if( m_Dialogs.GetAt( i ) == pDialog )\r
834             return true;\r
835 \r
836     // Add to the list.\r
837     if( FAILED( m_Dialogs.Add( pDialog ) ) )\r
838         return false;\r
839 \r
840     // Set up next and prev pointers.\r
841     if( m_Dialogs.GetSize() > 1 )\r
842         m_Dialogs[m_Dialogs.GetSize() - 2]->SetNextDialog( pDialog );\r
843     m_Dialogs[m_Dialogs.GetSize() - 1]->SetNextDialog( m_Dialogs[0] );\r
844 \r
845     return true;\r
846 }\r
847 \r
848 \r
849 //--------------------------------------------------------------------------------------\r
850 void CDXUTDialogResourceManager::UnregisterDialog( CDXUTDialog* pDialog )\r
851 {\r
852     // Search for the dialog in the list.\r
853     for( int i = 0; i < m_Dialogs.GetSize(); ++i )\r
854         if( m_Dialogs.GetAt( i ) == pDialog )\r
855         {\r
856             m_Dialogs.Remove( i );\r
857             if( m_Dialogs.GetSize() > 0 )\r
858             {\r
859                 int l, r;\r
860 \r
861                 if( 0 == i )\r
862                     l = m_Dialogs.GetSize() - 1;\r
863                 else\r
864                     l = i - 1;\r
865 \r
866                 if( m_Dialogs.GetSize() == i )\r
867                     r = 0;\r
868                 else\r
869                     r = i;\r
870 \r
871                 m_Dialogs[l]->SetNextDialog( m_Dialogs[r] );\r
872             }\r
873             return;\r
874         }\r
875 }\r
876 \r
877 \r
878 //--------------------------------------------------------------------------------------\r
879 void CDXUTDialogResourceManager::EnableKeyboardInputForAllDialogs()\r
880 {\r
881     // Enable keyboard input for all registered dialogs\r
882     for( int i = 0; i < m_Dialogs.GetSize(); ++i )\r
883         m_Dialogs[i]->EnableKeyboardInput( true );\r
884 }\r
885 \r
886 \r
887 //--------------------------------------------------------------------------------------\r
888 void CDXUTDialog::Refresh()\r
889 {\r
890     if( s_pControlFocus )\r
891         s_pControlFocus->OnFocusOut();\r
892 \r
893     if( m_pControlMouseOver )\r
894         m_pControlMouseOver->OnMouseLeave();\r
895 \r
896     s_pControlFocus = NULL;\r
897     s_pControlPressed = NULL;\r
898     m_pControlMouseOver = NULL;\r
899 \r
900     for( int i = 0; i < m_Controls.GetSize(); i++ )\r
901     {\r
902         CDXUTControl* pControl = m_Controls.GetAt( i );\r
903         pControl->Refresh();\r
904     }\r
905 \r
906     if( m_bKeyboardInput )\r
907         FocusDefaultControl();\r
908 }\r
909 \r
910 \r
911 //--------------------------------------------------------------------------------------\r
912 HRESULT CDXUTDialog::OnRender( float fElapsedTime )\r
913 {\r
914     if( m_pManager->GetD3D9Device() )\r
915         return OnRender9( fElapsedTime );\r
916     else\r
917         return OnRender11( fElapsedTime );\r
918 }\r
919 \r
920 \r
921 //--------------------------------------------------------------------------------------\r
922 HRESULT CDXUTDialog::OnRender9( float fElapsedTime )\r
923 {\r
924     // If this assert triggers, you need to call CDXUTDialogResourceManager::On*Device() from inside\r
925     // the application's device callbacks.  See the SDK samples for an example of how to do this.\r
926     assert( m_pManager->GetD3D9Device() && m_pManager->m_pStateBlock &&\r
927             L"To fix hook up CDXUTDialogResourceManager to device callbacks.  See comments for details" );\r
928 \r
929     // See if the dialog needs to be refreshed\r
930     if( m_fTimeLastRefresh < s_fTimeRefresh )\r
931     {\r
932         m_fTimeLastRefresh = DXUTGetTime();\r
933         Refresh();\r
934     }\r
935 \r
936     // For invisible dialog, out now.\r
937     if( !m_bVisible ||\r
938         ( m_bMinimized && !m_bCaption ) )\r
939         return S_OK;\r
940 \r
941     IDirect3DDevice9* pd3dDevice = m_pManager->GetD3D9Device();\r
942 \r
943     // Set up a state block here and restore it when finished drawing all the controls\r
944     m_pManager->m_pStateBlock->Capture();\r
945 \r
946     //pd3dDevice->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, TRUE);\r
947     //pd3dDevice->SetRenderState( D3DRS_SRGBWRITEENABLE, TRUE );\r
948    \r
949     pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );\r
950     pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );\r
951     pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );\r
952     pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );\r
953     pd3dDevice->SetRenderState( D3DRS_SEPARATEALPHABLENDENABLE, FALSE );\r
954     pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );\r
955     pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE |\r
956                                 D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED );\r
957     pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );\r
958     pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );\r
959     pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );\r
960     pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );\r
961     pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );\r
962 \r
963     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );\r
964     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );\r
965     pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );\r
966     pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );\r
967     pd3dDevice->SetTextureStageState( 0, D3DTSS_RESULTARG, D3DTA_CURRENT );\r
968     pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );\r
969     pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );\r
970 \r
971     BOOL bBackgroundIsVisible = ( m_colorTopLeft | m_colorTopRight | m_colorBottomRight | m_colorBottomLeft ) &\r
972         0xff000000;\r
973     if( !m_bMinimized && bBackgroundIsVisible )\r
974     {\r
975         DXUT_SCREEN_VERTEX_UNTEX vertices[4] =\r
976         {\r
977             ( float )m_x,           ( float )m_y,            0.5f, 1.0f, m_colorTopLeft,\r
978             ( float )m_x + m_width, ( float )m_y,            0.5f, 1.0f, m_colorTopRight,\r
979             ( float )m_x + m_width, ( float )m_y + m_height, 0.5f, 1.0f, m_colorBottomRight,\r
980             ( float )m_x,           ( float )m_y + m_height, 0.5f, 1.0f, m_colorBottomLeft,\r
981         };\r
982 \r
983         pd3dDevice->SetVertexShader( NULL );\r
984         pd3dDevice->SetPixelShader( NULL );\r
985 \r
986         pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );\r
987 \r
988         pd3dDevice->SetFVF( DXUT_SCREEN_VERTEX_UNTEX::FVF );\r
989         pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vertices, sizeof( DXUT_SCREEN_VERTEX_UNTEX ) );\r
990     }\r
991 \r
992     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );\r
993     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );\r
994     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );\r
995 \r
996     pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );\r
997     pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );\r
998     pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );\r
999 \r
1000     pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );\r
1001 \r
1002     DXUTTextureNode* pTextureNode = GetTexture( 0 );\r
1003     pd3dDevice->SetTexture( 0, pTextureNode->pTexture9 );\r
1004 \r
1005     m_pManager->m_pSprite->Begin( D3DXSPRITE_DONOTSAVESTATE );\r
1006 \r
1007     // Render the caption if it's enabled.\r
1008     if( m_bCaption )\r
1009     {\r
1010         // DrawSprite will offset the rect down by\r
1011         // m_nCaptionHeight, so adjust the rect higher\r
1012         // here to negate the effect.\r
1013         RECT rc =\r
1014         {\r
1015             0, -m_nCaptionHeight, m_width, 0\r
1016         };\r
1017         DrawSprite9( &m_CapElement, &rc );\r
1018         rc.left += 5; // Make a left margin\r
1019         WCHAR wszOutput[256];\r
1020         wcscpy_s( wszOutput, 256, m_wszCaption );\r
1021         if( m_bMinimized )\r
1022             wcscat_s( wszOutput, 256, L" (Minimized)" );\r
1023         DrawText9( wszOutput, &m_CapElement, &rc, true );\r
1024     }\r
1025 \r
1026     // If the dialog is minimized, skip rendering\r
1027     // its controls.\r
1028     if( !m_bMinimized )\r
1029     {\r
1030         for( int i = 0; i < m_Controls.GetSize(); i++ )\r
1031         {\r
1032             CDXUTControl* pControl = m_Controls.GetAt( i );\r
1033 \r
1034             // Focused control is drawn last\r
1035             if( pControl == s_pControlFocus )\r
1036                 continue;\r
1037 \r
1038             pControl->Render( fElapsedTime );\r
1039         }\r
1040 \r
1041         if( s_pControlFocus != NULL && s_pControlFocus->m_pDialog == this )\r
1042             s_pControlFocus->Render( fElapsedTime );\r
1043     }\r
1044 \r
1045     m_pManager->m_pSprite->End();\r
1046 \r
1047     m_pManager->m_pStateBlock->Apply();\r
1048 \r
1049     return S_OK;\r
1050 }\r
1051 \r
1052 \r
1053 \r
1054 //--------------------------------------------------------------------------------------\r
1055 HRESULT CDXUTDialog::OnRender11( float fElapsedTime )\r
1056 {\r
1057     // If this assert triggers, you need to call CDXUTDialogResourceManager::On*Device() from inside\r
1058     // the application's device callbacks.  See the SDK samples for an example of how to do this.\r
1059     assert( m_pManager->GetD3D11Device() &&\r
1060             L"To fix hook up CDXUTDialogResourceManager to device callbacks.  See comments for details" );\r
1061 \r
1062     // See if the dialog needs to be refreshed\r
1063     if( m_fTimeLastRefresh < s_fTimeRefresh )\r
1064     {\r
1065         m_fTimeLastRefresh = DXUTGetTime();\r
1066         Refresh();\r
1067     }\r
1068 \r
1069     // For invisible dialog, out now.\r
1070     if( !m_bVisible ||\r
1071         ( m_bMinimized && !m_bCaption ) )\r
1072         return S_OK;\r
1073 \r
1074     ID3D11Device* pd3dDevice = m_pManager->GetD3D11Device();\r
1075     ID3D11DeviceContext* pd3dDeviceContext = m_pManager->GetD3D11DeviceContext();\r
1076 \r
1077     // Set up a state block here and restore it when finished drawing all the controls\r
1078     m_pManager->StoreD3D11State( pd3dDeviceContext );\r
1079 \r
1080     BOOL bBackgroundIsVisible = ( m_colorTopLeft | m_colorTopRight | m_colorBottomRight | m_colorBottomLeft ) &\r
1081         0xff000000;\r
1082     if( !m_bMinimized && bBackgroundIsVisible )\r
1083     {\r
1084         // Convert the draw rectangle from screen coordinates to clip space coordinates.\r
1085         float Left, Right, Top, Bottom;\r
1086         Left = m_x * 2.0f / m_pManager->m_nBackBufferWidth - 1.0f;\r
1087         Right = ( m_x + m_width ) * 2.0f / m_pManager->m_nBackBufferWidth - 1.0f;\r
1088         Top = 1.0f - m_y * 2.0f / m_pManager->m_nBackBufferHeight;\r
1089         Bottom = 1.0f - ( m_y + m_height ) * 2.0f / m_pManager->m_nBackBufferHeight;\r
1090 \r
1091         DXUT_SCREEN_VERTEX_10 vertices[4] =\r
1092         {\r
1093             Left,  Top,    0.5f, D3DCOLOR_TO_D3DCOLORVALUE( m_colorTopLeft ), 0.0f, 0.0f,\r
1094             Right, Top,    0.5f, D3DCOLOR_TO_D3DCOLORVALUE( m_colorTopRight ), 1.0f, 0.0f,\r
1095             Left,  Bottom, 0.5f, D3DCOLOR_TO_D3DCOLORVALUE( m_colorBottomLeft ), 0.0f, 1.0f,\r
1096             Right, Bottom, 0.5f, D3DCOLOR_TO_D3DCOLORVALUE( m_colorBottomRight ), 1.0f, 1.0f,\r
1097         };\r
1098 \r
1099         //DXUT_SCREEN_VERTEX_10 *pVB;\r
1100         D3D11_MAPPED_SUBRESOURCE MappedData;\r
1101         if( SUCCEEDED( pd3dDeviceContext->Map( m_pManager->m_pVBScreenQuad11, 0, D3D11_MAP_WRITE_DISCARD,\r
1102                                                0, &MappedData ) ) )\r
1103         {\r
1104             CopyMemory( MappedData.pData, vertices, sizeof( vertices ) );\r
1105             pd3dDeviceContext->Unmap( m_pManager->m_pVBScreenQuad11, 0 );\r
1106         }\r
1107 \r
1108         // Set the quad VB as current\r
1109         UINT stride = sizeof( DXUT_SCREEN_VERTEX_10 );\r
1110         UINT offset = 0;\r
1111         pd3dDeviceContext->IASetVertexBuffers( 0, 1, &m_pManager->m_pVBScreenQuad11, &stride, &offset );\r
1112         pd3dDeviceContext->IASetInputLayout( m_pManager->m_pInputLayout11 );\r
1113         pd3dDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );\r
1114 \r
1115         // Setup for rendering\r
1116         m_pManager->ApplyRenderUIUntex11( pd3dDeviceContext );\r
1117         pd3dDeviceContext->Draw( 4, 0 );\r
1118     }\r
1119 \r
1120     DXUTTextureNode* pTextureNode = GetTexture( 0 );\r
1121     pd3dDeviceContext->PSSetShaderResources( 0, 1, &pTextureNode->pTexResView11 );\r
1122 \r
1123     // Sort depth back to front\r
1124     m_pManager->BeginSprites11();\r
1125     BeginText11();\r
1126 \r
1127     m_pManager->ApplyRenderUI11( pd3dDeviceContext );\r
1128 \r
1129     // Render the caption if it's enabled.\r
1130     if( m_bCaption )\r
1131     {\r
1132         // DrawSprite will offset the rect down by\r
1133         // m_nCaptionHeight, so adjust the rect higher\r
1134         // here to negate the effect.\r
1135         RECT rc = { 0, -m_nCaptionHeight, m_width, 0 };\r
1136         DrawSprite11( &m_CapElement, &rc, 0.99f );\r
1137         rc.left += 5; // Make a left margin\r
1138         WCHAR wszOutput[256];\r
1139         wcscpy_s( wszOutput, 256, m_wszCaption );\r
1140         if( m_bMinimized )\r
1141             wcscat_s( wszOutput, 256, L" (Minimized)" );\r
1142         DrawText11( pd3dDevice, pd3dDeviceContext, wszOutput, &m_CapElement, &rc, true );\r
1143     }\r
1144 \r
1145     // If the dialog is minimized, skip rendering\r
1146     // its controls.\r
1147     if( !m_bMinimized )\r
1148     {\r
1149         for( int i = 0; i < m_Controls.GetSize(); i++ )\r
1150         {\r
1151             CDXUTControl* pControl = m_Controls.GetAt( i );\r
1152 \r
1153             // Focused control is drawn last\r
1154             if( pControl == s_pControlFocus )\r
1155                 continue;\r
1156 \r
1157             pControl->Render( fElapsedTime );\r
1158         }\r
1159 \r
1160         if( s_pControlFocus != NULL && s_pControlFocus->m_pDialog == this )\r
1161             s_pControlFocus->Render( fElapsedTime );\r
1162     }\r
1163 \r
1164     // End sprites\r
1165     if( m_bCaption )\r
1166     {\r
1167         m_pManager->EndSprites11( pd3dDevice, pd3dDeviceContext );\r
1168         EndText11( pd3dDevice, pd3dDeviceContext );\r
1169     }\r
1170     m_pManager->RestoreD3D11State( pd3dDeviceContext );\r
1171 \r
1172     return S_OK;\r
1173 }\r
1174 \r
1175 //--------------------------------------------------------------------------------------\r
1176 VOID CDXUTDialog::SendEvent( UINT nEvent, bool bTriggeredByUser, CDXUTControl* pControl )\r
1177 {\r
1178     // If no callback has been registered there's nowhere to send the event to\r
1179     if( m_pCallbackEvent == NULL )\r
1180         return;\r
1181 \r
1182     // Discard events triggered programatically if these types of events haven't been\r
1183     // enabled\r
1184     if( !bTriggeredByUser && !m_bNonUserEvents )\r
1185         return;\r
1186 \r
1187     m_pCallbackEvent( nEvent, pControl->GetID(), pControl, m_pCallbackEventUserContext );\r
1188 }\r
1189 \r
1190 \r
1191 //--------------------------------------------------------------------------------------\r
1192 int CDXUTDialogResourceManager::AddFont( LPCWSTR strFaceName, LONG height, LONG weight ) \r
1193 {\r
1194     // See if this font already exists\r
1195     for( int i = 0; i < m_FontCache.GetSize(); i++ )\r
1196     {\r
1197         DXUTFontNode* pFontNode = m_FontCache.GetAt( i );\r
1198         size_t nLen = 0;\r
1199         nLen = wcsnlen( strFaceName, MAX_PATH);\r
1200         if( 0 == _wcsnicmp( pFontNode->strFace, strFaceName, nLen ) &&\r
1201             pFontNode->nHeight == height &&\r
1202             pFontNode->nWeight == weight )\r
1203         {\r
1204             return i;\r
1205         }\r
1206     }\r
1207 \r
1208     // Add a new font and try to create it\r
1209     DXUTFontNode* pNewFontNode = new DXUTFontNode;\r
1210     if( pNewFontNode == NULL )\r
1211         return -1;\r
1212 \r
1213     ZeroMemory( pNewFontNode, sizeof( DXUTFontNode ) );\r
1214     wcscpy_s( pNewFontNode->strFace, MAX_PATH, strFaceName );\r
1215     pNewFontNode->nHeight = height;\r
1216     pNewFontNode->nWeight = weight;\r
1217     m_FontCache.Add( pNewFontNode );\r
1218 \r
1219     int iFont = m_FontCache.GetSize() - 1;\r
1220 \r
1221     // If a device is available, try to create immediately\r
1222     if( m_pd3d9Device )\r
1223         CreateFont9( iFont );\r
1224 \r
1225     return iFont;\r
1226 }\r
1227 \r
1228 \r
1229 //--------------------------------------------------------------------------------------\r
1230 HRESULT CDXUTDialog::SetFont( UINT index, LPCWSTR strFaceName, LONG height, LONG weight )\r
1231 {\r
1232     // If this assert triggers, you need to call CDXUTDialog::Init() first.  This change\r
1233     // was made so that the DXUT's GUI could become seperate and optional from DXUT's core.  The \r
1234     // creation and interfacing with CDXUTDialogResourceManager is now the responsibility \r
1235     // of the application if it wishes to use DXUT's GUI.\r
1236     assert( m_pManager != NULL && L"To fix call CDXUTDialog::Init() first.  See comments for details." );\r
1237 \r
1238     // Make sure the list is at least as large as the index being set\r
1239     UINT i;\r
1240     for( i = m_Fonts.GetSize(); i <= index; i++ )\r
1241     {\r
1242         m_Fonts.Add( -1 );\r
1243     }\r
1244 \r
1245     int iFont = m_pManager->AddFont( strFaceName, height, weight );\r
1246     m_Fonts.SetAt( index, iFont );\r
1247 \r
1248     return S_OK;\r
1249 }\r
1250 \r
1251 \r
1252 //--------------------------------------------------------------------------------------\r
1253 DXUTFontNode* CDXUTDialog::GetFont( UINT index )\r
1254 {\r
1255     if( NULL == m_pManager )\r
1256         return NULL;\r
1257     return m_pManager->GetFontNode( m_Fonts.GetAt( index ) );\r
1258 }\r
1259 \r
1260 \r
1261 //--------------------------------------------------------------------------------------\r
1262 int CDXUTDialogResourceManager::AddTexture( LPCWSTR strFilename )\r
1263 {\r
1264     // See if this texture already exists\r
1265     for( int i = 0; i < m_TextureCache.GetSize(); i++ )\r
1266     {\r
1267         DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i );\r
1268         size_t nLen = 0;\r
1269         nLen = wcsnlen( strFilename, MAX_PATH);\r
1270         if( pTextureNode->bFileSource &&  // Sources must match\r
1271             0 == _wcsnicmp( pTextureNode->strFilename, strFilename, nLen ) )\r
1272         {\r
1273             return i;\r
1274         }\r
1275     }\r
1276 \r
1277     // Add a new texture and try to create it\r
1278     DXUTTextureNode* pNewTextureNode = new DXUTTextureNode;\r
1279     if( pNewTextureNode == NULL )\r
1280         return -1;\r
1281 \r
1282     ZeroMemory( pNewTextureNode, sizeof( DXUTTextureNode ) );\r
1283     pNewTextureNode->bFileSource = true;\r
1284     wcscpy_s( pNewTextureNode->strFilename, MAX_PATH, strFilename );\r
1285 \r
1286     m_TextureCache.Add( pNewTextureNode );\r
1287 \r
1288     int iTexture = m_TextureCache.GetSize() - 1;\r
1289 \r
1290     // If a device is available, try to create immediately\r
1291     if( m_pd3d9Device )\r
1292         CreateTexture9( iTexture );\r
1293 \r
1294     return iTexture;\r
1295 }\r
1296 \r
1297 \r
1298 //--------------------------------------------------------------------------------------\r
1299 int CDXUTDialogResourceManager::AddTexture( LPCWSTR strResourceName, HMODULE hResourceModule )\r
1300 {\r
1301     // See if this texture already exists\r
1302     for( int i = 0; i < m_TextureCache.GetSize(); i++ )\r
1303     {\r
1304         DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i );\r
1305         if( !pTextureNode->bFileSource &&      // Sources must match\r
1306             pTextureNode->hResourceModule == hResourceModule ) // Module handles must match\r
1307         {\r
1308             if( IS_INTRESOURCE( strResourceName ) )\r
1309             {\r
1310                 // Integer-based ID\r
1311                 if( ( INT_PTR )strResourceName == pTextureNode->nResourceID )\r
1312                     return i;\r
1313             }\r
1314             else\r
1315             {\r
1316                 // String-based ID\r
1317                 size_t nLen = 0;\r
1318                 nLen = wcsnlen ( strResourceName, MAX_PATH );\r
1319                 if( 0 == _wcsnicmp( pTextureNode->strFilename, strResourceName, nLen ) )\r
1320                     return i;\r
1321             }\r
1322         }\r
1323     }\r
1324 \r
1325     // Add a new texture and try to create it\r
1326     DXUTTextureNode* pNewTextureNode = new DXUTTextureNode;\r
1327     if( pNewTextureNode == NULL )\r
1328         return -1;\r
1329 \r
1330     ZeroMemory( pNewTextureNode, sizeof( DXUTTextureNode ) );\r
1331     pNewTextureNode->hResourceModule = hResourceModule;\r
1332     if( IS_INTRESOURCE( strResourceName ) )\r
1333     {\r
1334         pNewTextureNode->nResourceID = ( int )( size_t )strResourceName;\r
1335     }\r
1336     else\r
1337     {\r
1338         pNewTextureNode->nResourceID = 0;\r
1339         wcscpy_s( pNewTextureNode->strFilename, MAX_PATH, strResourceName );\r
1340     }\r
1341 \r
1342     m_TextureCache.Add( pNewTextureNode );\r
1343 \r
1344     int iTexture = m_TextureCache.GetSize() - 1;\r
1345 \r
1346     // If a device is available, try to create immediately\r
1347     if( m_pd3d9Device )\r
1348         CreateTexture9( iTexture );\r
1349 \r
1350     return iTexture;\r
1351 }\r
1352 \r
1353 \r
1354 //--------------------------------------------------------------------------------------\r
1355 HRESULT CDXUTDialog::SetTexture( UINT index, LPCWSTR strFilename )\r
1356 {\r
1357     // If this assert triggers, you need to call CDXUTDialog::Init() first.  This change\r
1358     // was made so that the DXUT's GUI could become seperate and optional from DXUT's core.  The \r
1359     // creation and interfacing with CDXUTDialogResourceManager is now the responsibility \r
1360     // of the application if it wishes to use DXUT's GUI.\r
1361     assert( m_pManager != NULL && L"To fix this, call CDXUTDialog::Init() first.  See comments for details." );\r
1362 \r
1363     // Make sure the list is at least as large as the index being set\r
1364     for( UINT i = m_Textures.GetSize(); i <= index; i++ )\r
1365     {\r
1366         m_Textures.Add( -1 );\r
1367     }\r
1368 \r
1369     int iTexture = m_pManager->AddTexture( strFilename );\r
1370 \r
1371     m_Textures.SetAt( index, iTexture );\r
1372     return S_OK;\r
1373 }\r
1374 \r
1375 \r
1376 //--------------------------------------------------------------------------------------\r
1377 HRESULT CDXUTDialog::SetTexture( UINT index, LPCWSTR strResourceName, HMODULE hResourceModule )\r
1378 {\r
1379     // If this assert triggers, you need to call CDXUTDialog::Init() first.  This change\r
1380     // was made so that the DXUT's GUI could become seperate and optional from DXUT's core.  The \r
1381     // creation and interfacing with CDXUTDialogResourceManager is now the responsibility \r
1382     // of the application if it wishes to use DXUT's GUI.\r
1383     assert( m_pManager != NULL && L"To fix this, call CDXUTDialog::Init() first.  See comments for details." );\r
1384 \r
1385     // Make sure the list is at least as large as the index being set\r
1386     for( UINT i = m_Textures.GetSize(); i <= index; i++ )\r
1387     {\r
1388         m_Textures.Add( -1 );\r
1389     }\r
1390 \r
1391     int iTexture = m_pManager->AddTexture( strResourceName, hResourceModule );\r
1392 \r
1393     m_Textures.SetAt( index, iTexture );\r
1394     return S_OK;\r
1395 }\r
1396 \r
1397 \r
1398 //--------------------------------------------------------------------------------------\r
1399 DXUTTextureNode* CDXUTDialog::GetTexture( UINT index )\r
1400 {\r
1401     if( NULL == m_pManager )\r
1402         return NULL;\r
1403     return m_pManager->GetTextureNode( m_Textures.GetAt( index ) );\r
1404 }\r
1405 \r
1406 \r
1407 \r
1408 //--------------------------------------------------------------------------------------\r
1409 bool CDXUTDialog::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )\r
1410 {\r
1411     bool bHandled = false;\r
1412 \r
1413     // For invisible dialog, do not handle anything.\r
1414     if( !m_bVisible )\r
1415         return false;\r
1416 \r
1417     // If automation command-line switch is on, enable this dialog's keyboard input\r
1418     // upon any key press or mouse click.\r
1419     if( DXUTGetAutomation() &&\r
1420         ( WM_LBUTTONDOWN == uMsg || WM_LBUTTONDBLCLK == uMsg || WM_KEYDOWN == uMsg ) )\r
1421     {\r
1422         m_pManager->EnableKeyboardInputForAllDialogs();\r
1423     }\r
1424 \r
1425     // If caption is enable, check for clicks in the caption area.\r
1426     if( m_bCaption )\r
1427     {\r
1428         if( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK )\r
1429         {\r
1430             POINT mousePoint =\r
1431             {\r
1432                 short( LOWORD( lParam ) ), short( HIWORD( lParam ) )\r
1433             };\r
1434 \r
1435             if( mousePoint.x >= m_x && mousePoint.x < m_x + m_width &&\r
1436                 mousePoint.y >= m_y && mousePoint.y < m_y + m_nCaptionHeight )\r
1437             {\r
1438                 m_bDrag = true;\r
1439                 SetCapture( DXUTGetHWND() );\r
1440                 return true;\r
1441             }\r
1442         }\r
1443         else if( uMsg == WM_LBUTTONUP && m_bDrag )\r
1444         {\r
1445             POINT mousePoint =\r
1446             {\r
1447                 short( LOWORD( lParam ) ), short( HIWORD( lParam ) )\r
1448             };\r
1449 \r
1450             if( mousePoint.x >= m_x && mousePoint.x < m_x + m_width &&\r
1451                 mousePoint.y >= m_y && mousePoint.y < m_y + m_nCaptionHeight )\r
1452             {\r
1453                 ReleaseCapture();\r
1454                 m_bDrag = false;\r
1455                 m_bMinimized = !m_bMinimized;\r
1456                 return true;\r
1457             }\r
1458         }\r
1459     }\r
1460 \r
1461     // If the dialog is minimized, don't send any messages to controls.\r
1462     if( m_bMinimized )\r
1463         return false;\r
1464 \r
1465     // If a control is in focus, it belongs to this dialog, and it's enabled, then give\r
1466     // it the first chance at handling the message.\r
1467     if( s_pControlFocus &&\r
1468         s_pControlFocus->m_pDialog == this &&\r
1469         s_pControlFocus->GetEnabled() )\r
1470     {\r
1471         // If the control MsgProc handles it, then we don't.\r
1472         if( s_pControlFocus->MsgProc( uMsg, wParam, lParam ) )\r
1473             return true;\r
1474     }\r
1475 \r
1476     switch( uMsg )\r
1477     {\r
1478         case WM_SIZE:\r
1479         case WM_MOVE:\r
1480             {\r
1481                 // Handle sizing and moving messages so that in case the mouse cursor is moved out\r
1482                 // of an UI control because of the window adjustment, we can properly\r
1483                 // unhighlight the highlighted control.\r
1484                 POINT pt =\r
1485                 {\r
1486                     -1, -1\r
1487                 };\r
1488                 OnMouseMove( pt );\r
1489                 break;\r
1490             }\r
1491 \r
1492         case WM_ACTIVATEAPP:\r
1493             // Call OnFocusIn()/OnFocusOut() of the control that currently has the focus\r
1494             // as the application is activated/deactivated.  This matches the Windows\r
1495             // behavior.\r
1496             if( s_pControlFocus &&\r
1497                 s_pControlFocus->m_pDialog == this &&\r
1498                 s_pControlFocus->GetEnabled() )\r
1499             {\r
1500                 if( wParam )\r
1501                     s_pControlFocus->OnFocusIn();\r
1502                 else\r
1503                     s_pControlFocus->OnFocusOut();\r
1504             }\r
1505             break;\r
1506 \r
1507             // Keyboard messages\r
1508         case WM_KEYDOWN:\r
1509         case WM_SYSKEYDOWN:\r
1510         case WM_KEYUP:\r
1511         case WM_SYSKEYUP:\r
1512             {\r
1513                 // If a control is in focus, it belongs to this dialog, and it's enabled, then give\r
1514                 // it the first chance at handling the message.\r
1515                 if( s_pControlFocus &&\r
1516                     s_pControlFocus->m_pDialog == this &&\r
1517                     s_pControlFocus->GetEnabled() )\r
1518                 {\r
1519                     if( s_pControlFocus->HandleKeyboard( uMsg, wParam, lParam ) )\r
1520                         return true;\r
1521                 }\r
1522 \r
1523                 // Not yet handled, see if this matches a control's hotkey\r
1524                 // Activate the hotkey if the focus doesn't belong to an\r
1525                 // edit box.\r
1526                 if( uMsg == WM_KEYDOWN && ( !s_pControlFocus ||\r
1527                                             ( s_pControlFocus->GetType() != DXUT_CONTROL_EDITBOX\r
1528                                               && s_pControlFocus->GetType() != DXUT_CONTROL_IMEEDITBOX ) ) )\r
1529                 {\r
1530                     for( int i = 0; i < m_Controls.GetSize(); i++ )\r
1531                     {\r
1532                         CDXUTControl* pControl = m_Controls.GetAt( i );\r
1533                         if( pControl->GetHotkey() == wParam )\r
1534                         {\r
1535                             pControl->OnHotkey();\r
1536                             return true;\r
1537                         }\r
1538                     }\r
1539                 }\r
1540 \r
1541                 // Not yet handled, check for focus messages\r
1542                 if( uMsg == WM_KEYDOWN )\r
1543                 {\r
1544                     // If keyboard input is not enabled, this message should be ignored\r
1545                     if( !m_bKeyboardInput )\r
1546                         return false;\r
1547 \r
1548                     switch( wParam )\r
1549                     {\r
1550                         case VK_RIGHT:\r
1551                         case VK_DOWN:\r
1552                             if( s_pControlFocus != NULL )\r
1553                             {\r
1554                                 return OnCycleFocus( true );\r
1555                             }\r
1556                             break;\r
1557 \r
1558                         case VK_LEFT:\r
1559                         case VK_UP:\r
1560                             if( s_pControlFocus != NULL )\r
1561                             {\r
1562                                 return OnCycleFocus( false );\r
1563                             }\r
1564                             break;\r
1565 \r
1566                         case VK_TAB:\r
1567                         {\r
1568                             bool bShiftDown = ( ( GetKeyState( VK_SHIFT ) & 0x8000 ) != 0 );\r
1569                             return OnCycleFocus( !bShiftDown );\r
1570                         }\r
1571                     }\r
1572                 }\r
1573 \r
1574                 break;\r
1575             }\r
1576 \r
1577 \r
1578             // Mouse messages\r
1579         case WM_MOUSEMOVE:\r
1580         case WM_LBUTTONDOWN:\r
1581         case WM_LBUTTONUP:\r
1582         case WM_MBUTTONDOWN:\r
1583         case WM_MBUTTONUP:\r
1584         case WM_RBUTTONDOWN:\r
1585         case WM_RBUTTONUP:\r
1586         case WM_XBUTTONDOWN:\r
1587         case WM_XBUTTONUP:\r
1588         case WM_LBUTTONDBLCLK:\r
1589         case WM_MBUTTONDBLCLK:\r
1590         case WM_RBUTTONDBLCLK:\r
1591         case WM_XBUTTONDBLCLK:\r
1592         case WM_MOUSEWHEEL:\r
1593             {\r
1594                 // If not accepting mouse input, return false to indicate the message should still \r
1595                 // be handled by the application (usually to move the camera).\r
1596                 if( !m_bMouseInput )\r
1597                     return false;\r
1598 \r
1599                 POINT mousePoint =\r
1600                 {\r
1601                     short( LOWORD( lParam ) ), short( HIWORD( lParam ) )\r
1602                 };\r
1603                 mousePoint.x -= m_x;\r
1604                 mousePoint.y -= m_y;\r
1605 \r
1606                 // If caption is enabled, offset the Y coordinate by the negative of its height.\r
1607                 if( m_bCaption )\r
1608                     mousePoint.y -= m_nCaptionHeight;\r
1609 \r
1610                 // If a control is in focus, it belongs to this dialog, and it's enabled, then give\r
1611                 // it the first chance at handling the message.\r
1612                 if( s_pControlFocus &&\r
1613                     s_pControlFocus->m_pDialog == this &&\r
1614                     s_pControlFocus->GetEnabled() )\r
1615                 {\r
1616                     if( s_pControlFocus->HandleMouse( uMsg, mousePoint, wParam, lParam ) )\r
1617                         return true;\r
1618                 }\r
1619 \r
1620                 // Not yet handled, see if the mouse is over any controls\r
1621                 CDXUTControl* pControl = GetControlAtPoint( mousePoint );\r
1622                 if( pControl != NULL && pControl->GetEnabled() )\r
1623                 {\r
1624                     bHandled = pControl->HandleMouse( uMsg, mousePoint, wParam, lParam );\r
1625                     if( bHandled )\r
1626                         return true;\r
1627                 }\r
1628                 else\r
1629                 {\r
1630                     // Mouse not over any controls in this dialog, if there was a control\r
1631                     // which had focus it just lost it\r
1632                     if( uMsg == WM_LBUTTONDOWN &&\r
1633                         s_pControlFocus &&\r
1634                         s_pControlFocus->m_pDialog == this )\r
1635                     {\r
1636                         s_pControlFocus->OnFocusOut();\r
1637                         s_pControlFocus = NULL;\r
1638                     }\r
1639                 }\r
1640 \r
1641                 // Still not handled, hand this off to the dialog. Return false to indicate the\r
1642                 // message should still be handled by the application (usually to move the camera).\r
1643                 switch( uMsg )\r
1644                 {\r
1645                     case WM_MOUSEMOVE:\r
1646                         OnMouseMove( mousePoint );\r
1647                         return false;\r
1648                 }\r
1649 \r
1650                 break;\r
1651             }\r
1652 \r
1653         case WM_CAPTURECHANGED:\r
1654         {\r
1655             // The application has lost mouse capture.\r
1656             // The dialog object may not have received\r
1657             // a WM_MOUSEUP when capture changed. Reset\r
1658             // m_bDrag so that the dialog does not mistakenly\r
1659             // think the mouse button is still held down.\r
1660             if( ( HWND )lParam != hWnd )\r
1661                 m_bDrag = false;\r
1662         }\r
1663     }\r
1664 \r
1665     return false;\r
1666 }\r
1667 \r
1668 //--------------------------------------------------------------------------------------\r
1669 CDXUTControl* CDXUTDialog::GetControlAtPoint( POINT pt )\r
1670 {\r
1671     // Search through all child controls for the first one which\r
1672     // contains the mouse point\r
1673     for( int i = 0; i < m_Controls.GetSize(); i++ )\r
1674     {\r
1675         CDXUTControl* pControl = m_Controls.GetAt( i );\r
1676 \r
1677         if( pControl == NULL )\r
1678         {\r
1679             continue;\r
1680         }\r
1681 \r
1682         // We only return the current control if it is visible\r
1683         // and enabled.  Because GetControlAtPoint() is used to do mouse\r
1684         // hittest, it makes sense to perform this filtering.\r
1685         if( pControl->ContainsPoint( pt ) && pControl->GetEnabled() && pControl->GetVisible() )\r
1686         {\r
1687             return pControl;\r
1688         }\r
1689     }\r
1690 \r
1691     return NULL;\r
1692 }\r
1693 \r
1694 \r
1695 //--------------------------------------------------------------------------------------\r
1696 bool CDXUTDialog::GetControlEnabled( int ID )\r
1697 {\r
1698     CDXUTControl* pControl = GetControl( ID );\r
1699     if( pControl == NULL )\r
1700         return false;\r
1701 \r
1702     return pControl->GetEnabled();\r
1703 }\r
1704 \r
1705 \r
1706 \r
1707 //--------------------------------------------------------------------------------------\r
1708 void CDXUTDialog::SetControlEnabled( int ID, bool bEnabled )\r
1709 {\r
1710     CDXUTControl* pControl = GetControl( ID );\r
1711     if( pControl == NULL )\r
1712         return;\r
1713 \r
1714     pControl->SetEnabled( bEnabled );\r
1715 }\r
1716 \r
1717 \r
1718 //--------------------------------------------------------------------------------------\r
1719 void CDXUTDialog::OnMouseUp( POINT pt )\r
1720 {\r
1721     s_pControlPressed = NULL;\r
1722     m_pControlMouseOver = NULL;\r
1723 }\r
1724 \r
1725 \r
1726 //--------------------------------------------------------------------------------------\r
1727 void CDXUTDialog::OnMouseMove( POINT pt )\r
1728 {\r
1729     // Figure out which control the mouse is over now\r
1730     CDXUTControl* pControl = GetControlAtPoint( pt );\r
1731 \r
1732     // If the mouse is still over the same control, nothing needs to be done\r
1733     if( pControl == m_pControlMouseOver )\r
1734         return;\r
1735 \r
1736     // Handle mouse leaving the old control\r
1737     if( m_pControlMouseOver )\r
1738         m_pControlMouseOver->OnMouseLeave();\r
1739 \r
1740     // Handle mouse entering the new control\r
1741     m_pControlMouseOver = pControl;\r
1742     if( pControl != NULL )\r
1743         m_pControlMouseOver->OnMouseEnter();\r
1744 }\r
1745 \r
1746 \r
1747 //--------------------------------------------------------------------------------------\r
1748 HRESULT CDXUTDialog::SetDefaultElement( UINT nControlType, UINT iElement, CDXUTElement* pElement )\r
1749 {\r
1750     // If this Element type already exist in the list, simply update the stored Element\r
1751     for( int i = 0; i < m_DefaultElements.GetSize(); i++ )\r
1752     {\r
1753         DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i );\r
1754 \r
1755         if( pElementHolder->nControlType == nControlType &&\r
1756             pElementHolder->iElement == iElement )\r
1757         {\r
1758             pElementHolder->Element = *pElement;\r
1759             return S_OK;\r
1760         }\r
1761     }\r
1762 \r
1763     // Otherwise, add a new entry\r
1764     DXUTElementHolder* pNewHolder;\r
1765     pNewHolder = new DXUTElementHolder;\r
1766     if( pNewHolder == NULL )\r
1767         return E_OUTOFMEMORY;\r
1768 \r
1769     pNewHolder->nControlType = nControlType;\r
1770     pNewHolder->iElement = iElement;\r
1771     pNewHolder->Element = *pElement;\r
1772 \r
1773     HRESULT hr = m_DefaultElements.Add( pNewHolder );\r
1774     if( FAILED( hr ) )\r
1775     {\r
1776         delete pNewHolder;\r
1777     }\r
1778     return hr;\r
1779 }\r
1780 \r
1781 \r
1782 //--------------------------------------------------------------------------------------\r
1783 CDXUTElement* CDXUTDialog::GetDefaultElement( UINT nControlType, UINT iElement )\r
1784 {\r
1785     for( int i = 0; i < m_DefaultElements.GetSize(); i++ )\r
1786     {\r
1787         DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i );\r
1788 \r
1789         if( pElementHolder->nControlType == nControlType &&\r
1790             pElementHolder->iElement == iElement )\r
1791         {\r
1792             return &pElementHolder->Element;\r
1793         }\r
1794     }\r
1795 \r
1796     return NULL;\r
1797 }\r
1798 \r
1799 \r
1800 \r
1801 //--------------------------------------------------------------------------------------\r
1802 HRESULT CDXUTDialog::AddStatic( int ID, LPCWSTR strText, int x, int y, int width, int height, bool bIsDefault,\r
1803                                 CDXUTStatic** ppCreated )\r
1804 {\r
1805     HRESULT hr = S_OK;\r
1806 \r
1807     CDXUTStatic* pStatic = new CDXUTStatic( this );\r
1808 \r
1809     if( ppCreated != NULL )\r
1810         *ppCreated = pStatic;\r
1811 \r
1812     if( pStatic == NULL )\r
1813         return E_OUTOFMEMORY;\r
1814 \r
1815     hr = AddControl( pStatic );\r
1816     if( FAILED( hr ) )\r
1817         return hr;\r
1818 \r
1819     // Set the ID and list index\r
1820     pStatic->SetID( ID );\r
1821     pStatic->SetText( strText );\r
1822     pStatic->SetLocation( x, y );\r
1823     pStatic->SetSize( width, height );\r
1824     pStatic->m_bIsDefault = bIsDefault;\r
1825 \r
1826     return S_OK;\r
1827 }\r
1828 \r
1829 \r
1830 //--------------------------------------------------------------------------------------\r
1831 HRESULT CDXUTDialog::AddButton( int ID, LPCWSTR strText, int x, int y, int width, int height, UINT nHotkey,\r
1832                                 bool bIsDefault, CDXUTButton** ppCreated )\r
1833 {\r
1834     HRESULT hr = S_OK;\r
1835 \r
1836     CDXUTButton* pButton = new CDXUTButton( this );\r
1837 \r
1838     if( ppCreated != NULL )\r
1839         *ppCreated = pButton;\r
1840 \r
1841     if( pButton == NULL )\r
1842         return E_OUTOFMEMORY;\r
1843 \r
1844     hr = AddControl( pButton );\r
1845     if( FAILED( hr ) )\r
1846         return hr;\r
1847 \r
1848     // Set the ID and list index\r
1849     pButton->SetID( ID );\r
1850     pButton->SetText( strText );\r
1851     pButton->SetLocation( x, y );\r
1852     pButton->SetSize( width, height );\r
1853     pButton->SetHotkey( nHotkey );\r
1854     pButton->m_bIsDefault = bIsDefault;\r
1855 \r
1856     return S_OK;\r
1857 }\r
1858 \r
1859 \r
1860 //--------------------------------------------------------------------------------------\r
1861 HRESULT CDXUTDialog::AddCheckBox( int ID, LPCWSTR strText, int x, int y, int width, int height, bool bChecked,\r
1862                                   UINT nHotkey, bool bIsDefault, CDXUTCheckBox** ppCreated )\r
1863 {\r
1864     HRESULT hr = S_OK;\r
1865 \r
1866     CDXUTCheckBox* pCheckBox = new CDXUTCheckBox( this );\r
1867 \r
1868     if( ppCreated != NULL )\r
1869         *ppCreated = pCheckBox;\r
1870 \r
1871     if( pCheckBox == NULL )\r
1872         return E_OUTOFMEMORY;\r
1873 \r
1874     hr = AddControl( pCheckBox );\r
1875     if( FAILED( hr ) )\r
1876         return hr;\r
1877 \r
1878     // Set the ID and list index\r
1879     pCheckBox->SetID( ID );\r
1880     pCheckBox->SetText( strText );\r
1881     pCheckBox->SetLocation( x, y );\r
1882     pCheckBox->SetSize( width, height );\r
1883     pCheckBox->SetHotkey( nHotkey );\r
1884     pCheckBox->m_bIsDefault = bIsDefault;\r
1885     pCheckBox->SetChecked( bChecked );\r
1886 \r
1887     return S_OK;\r
1888 }\r
1889 \r
1890 \r
1891 \r
1892 //--------------------------------------------------------------------------------------\r
1893 HRESULT CDXUTDialog::AddRadioButton( int ID, UINT nButtonGroup, LPCWSTR strText, int x, int y, int width, int height,\r
1894                                      bool bChecked, UINT nHotkey, bool bIsDefault, CDXUTRadioButton** ppCreated )\r
1895 {\r
1896     HRESULT hr = S_OK;\r
1897 \r
1898     CDXUTRadioButton* pRadioButton = new CDXUTRadioButton( this );\r
1899 \r
1900     if( ppCreated != NULL )\r
1901         *ppCreated = pRadioButton;\r
1902 \r
1903     if( pRadioButton == NULL )\r
1904         return E_OUTOFMEMORY;\r
1905 \r
1906     hr = AddControl( pRadioButton );\r
1907     if( FAILED( hr ) )\r
1908         return hr;\r
1909 \r
1910     // Set the ID and list index\r
1911     pRadioButton->SetID( ID );\r
1912     pRadioButton->SetText( strText );\r
1913     pRadioButton->SetButtonGroup( nButtonGroup );\r
1914     pRadioButton->SetLocation( x, y );\r
1915     pRadioButton->SetSize( width, height );\r
1916     pRadioButton->SetHotkey( nHotkey );\r
1917     pRadioButton->SetChecked( bChecked );\r
1918     pRadioButton->m_bIsDefault = bIsDefault;\r
1919     pRadioButton->SetChecked( bChecked );\r
1920 \r
1921     return S_OK;\r
1922 }\r
1923 \r
1924 \r
1925 \r
1926 \r
1927 //--------------------------------------------------------------------------------------\r
1928 HRESULT CDXUTDialog::AddComboBox( int ID, int x, int y, int width, int height, UINT nHotkey, bool bIsDefault,\r
1929                                   CDXUTComboBox** ppCreated )\r
1930 {\r
1931     HRESULT hr = S_OK;\r
1932 \r
1933     CDXUTComboBox* pComboBox = new CDXUTComboBox( this );\r
1934 \r
1935     if( ppCreated != NULL )\r
1936         *ppCreated = pComboBox;\r
1937 \r
1938     if( pComboBox == NULL )\r
1939         return E_OUTOFMEMORY;\r
1940 \r
1941     hr = AddControl( pComboBox );\r
1942     if( FAILED( hr ) )\r
1943         return hr;\r
1944 \r
1945     // Set the ID and list index\r
1946     pComboBox->SetID( ID );\r
1947     pComboBox->SetLocation( x, y );\r
1948     pComboBox->SetSize( width, height );\r
1949     pComboBox->SetHotkey( nHotkey );\r
1950     pComboBox->m_bIsDefault = bIsDefault;\r
1951 \r
1952     return S_OK;\r
1953 }\r
1954 \r
1955 \r
1956 \r
1957 //--------------------------------------------------------------------------------------\r
1958 HRESULT CDXUTDialog::AddSlider( int ID, int x, int y, int width, int height, int min, int max, int value,\r
1959                                 bool bIsDefault, CDXUTSlider** ppCreated )\r
1960 {\r
1961     HRESULT hr = S_OK;\r
1962 \r
1963     CDXUTSlider* pSlider = new CDXUTSlider( this );\r
1964 \r
1965     if( ppCreated != NULL )\r
1966         *ppCreated = pSlider;\r
1967 \r
1968     if( pSlider == NULL )\r
1969         return E_OUTOFMEMORY;\r
1970 \r
1971     hr = AddControl( pSlider );\r
1972     if( FAILED( hr ) )\r
1973         return hr;\r
1974 \r
1975     // Set the ID and list index\r
1976     pSlider->SetID( ID );\r
1977     pSlider->SetLocation( x, y );\r
1978     pSlider->SetSize( width, height );\r
1979     pSlider->m_bIsDefault = bIsDefault;\r
1980     pSlider->SetRange( min, max );\r
1981     pSlider->SetValue( value );\r
1982     pSlider->UpdateRects();\r
1983 \r
1984     return S_OK;\r
1985 }\r
1986 \r
1987 \r
1988 \r
1989 //--------------------------------------------------------------------------------------\r
1990 HRESULT CDXUTDialog::AddEditBox( int ID, LPCWSTR strText, int x, int y, int width, int height, bool bIsDefault,\r
1991                                  CDXUTEditBox** ppCreated )\r
1992 {\r
1993     HRESULT hr = S_OK;\r
1994 \r
1995     CDXUTEditBox* pEditBox = new CDXUTEditBox( this );\r
1996 \r
1997     if( ppCreated != NULL )\r
1998         *ppCreated = pEditBox;\r
1999 \r
2000     if( pEditBox == NULL )\r
2001         return E_OUTOFMEMORY;\r
2002 \r
2003     hr = AddControl( pEditBox );\r
2004     if( FAILED( hr ) )\r
2005         return hr;\r
2006 \r
2007     // Set the ID and position\r
2008     pEditBox->SetID( ID );\r
2009     pEditBox->SetLocation( x, y );\r
2010     pEditBox->SetSize( width, height );\r
2011     pEditBox->m_bIsDefault = bIsDefault;\r
2012 \r
2013     if( strText )\r
2014         pEditBox->SetText( strText );\r
2015 \r
2016     return S_OK;\r
2017 }\r
2018 \r
2019 \r
2020 //--------------------------------------------------------------------------------------\r
2021 HRESULT CDXUTDialog::AddListBox( int ID, int x, int y, int width, int height, DWORD dwStyle, CDXUTListBox** ppCreated )\r
2022 {\r
2023     HRESULT hr = S_OK;\r
2024     CDXUTListBox* pListBox = new CDXUTListBox( this );\r
2025 \r
2026     if( ppCreated != NULL )\r
2027         *ppCreated = pListBox;\r
2028 \r
2029     if( pListBox == NULL )\r
2030         return E_OUTOFMEMORY;\r
2031 \r
2032     hr = AddControl( pListBox );\r
2033     if( FAILED( hr ) )\r
2034         return hr;\r
2035 \r
2036     // Set the ID and position\r
2037     pListBox->SetID( ID );\r
2038     pListBox->SetLocation( x, y );\r
2039     pListBox->SetSize( width, height );\r
2040     pListBox->SetStyle( dwStyle );\r
2041 \r
2042     return S_OK;\r
2043 }\r
2044 \r
2045 \r
2046 \r
2047 //--------------------------------------------------------------------------------------\r
2048 HRESULT CDXUTDialog::InitControl( CDXUTControl* pControl )\r
2049 {\r
2050     HRESULT hr;\r
2051 \r
2052     if( pControl == NULL )\r
2053         return E_INVALIDARG;\r
2054 \r
2055     pControl->m_Index = m_Controls.GetSize();\r
2056 \r
2057     // Look for a default Element entries\r
2058     for( int i = 0; i < m_DefaultElements.GetSize(); i++ )\r
2059     {\r
2060         DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i );\r
2061         if( pElementHolder->nControlType == pControl->GetType() )\r
2062             pControl->SetElement( pElementHolder->iElement, &pElementHolder->Element );\r
2063     }\r
2064 \r
2065     V_RETURN( pControl->OnInit() );\r
2066 \r
2067     return S_OK;\r
2068 }\r
2069 \r
2070 \r
2071 \r
2072 //--------------------------------------------------------------------------------------\r
2073 HRESULT CDXUTDialog::AddControl( CDXUTControl* pControl )\r
2074 {\r
2075     HRESULT hr = S_OK;\r
2076 \r
2077     hr = InitControl( pControl );\r
2078     if( FAILED( hr ) )\r
2079         return DXTRACE_ERR( L"CDXUTDialog::InitControl", hr );\r
2080 \r
2081     // Add to the list\r
2082     hr = m_Controls.Add( pControl );\r
2083     if( FAILED( hr ) )\r
2084     {\r
2085         return DXTRACE_ERR( L"CGrowableArray::Add", hr );\r
2086     }\r
2087 \r
2088     return S_OK;\r
2089 }\r
2090 \r
2091 \r
2092 //--------------------------------------------------------------------------------------\r
2093 CDXUTControl* CDXUTDialog::GetControl( int ID )\r
2094 {\r
2095     // Try to find the control with the given ID\r
2096     for( int i = 0; i < m_Controls.GetSize(); i++ )\r
2097     {\r
2098         CDXUTControl* pControl = m_Controls.GetAt( i );\r
2099 \r
2100         if( pControl->GetID() == ID )\r
2101         {\r
2102             return pControl;\r
2103         }\r
2104     }\r
2105 \r
2106     // Not found\r
2107     return NULL;\r
2108 }\r
2109 \r
2110 \r
2111 \r
2112 //--------------------------------------------------------------------------------------\r
2113 CDXUTControl* CDXUTDialog::GetControl( int ID, UINT nControlType )\r
2114 {\r
2115     // Try to find the control with the given ID\r
2116     for( int i = 0; i < m_Controls.GetSize(); i++ )\r
2117     {\r
2118         CDXUTControl* pControl = m_Controls.GetAt( i );\r
2119 \r
2120         if( pControl->GetID() == ID && pControl->GetType() == nControlType )\r
2121         {\r
2122             return pControl;\r
2123         }\r
2124     }\r
2125 \r
2126     // Not found\r
2127     return NULL;\r
2128 }\r
2129 \r
2130 \r
2131 \r
2132 //--------------------------------------------------------------------------------------\r
2133 CDXUTControl* CDXUTDialog::GetNextControl( CDXUTControl* pControl )\r
2134 {\r
2135     int index = pControl->m_Index + 1;\r
2136 \r
2137     CDXUTDialog* pDialog = pControl->m_pDialog;\r
2138 \r
2139     // Cycle through dialogs in the loop to find the next control. Note\r
2140     // that if only one control exists in all looped dialogs it will\r
2141     // be the returned 'next' control.\r
2142     while( index >= ( int )pDialog->m_Controls.GetSize() )\r
2143     {\r
2144         pDialog = pDialog->m_pNextDialog;\r
2145         index = 0;\r
2146     }\r
2147 \r
2148     return pDialog->m_Controls.GetAt( index );\r
2149 }\r
2150 \r
2151 //--------------------------------------------------------------------------------------\r
2152 CDXUTControl* CDXUTDialog::GetPrevControl( CDXUTControl* pControl )\r
2153 {\r
2154     int index = pControl->m_Index - 1;\r
2155 \r
2156     CDXUTDialog* pDialog = pControl->m_pDialog;\r
2157 \r
2158     // Cycle through dialogs in the loop to find the next control. Note\r
2159     // that if only one control exists in all looped dialogs it will\r
2160     // be the returned 'previous' control.\r
2161     while( index < 0 )\r
2162     {\r
2163         pDialog = pDialog->m_pPrevDialog;\r
2164         if( pDialog == NULL )\r
2165             pDialog = pControl->m_pDialog;\r
2166 \r
2167         index = pDialog->m_Controls.GetSize() - 1;\r
2168     }\r
2169 \r
2170     return pDialog->m_Controls.GetAt( index );\r
2171 }\r
2172 \r
2173 \r
2174 //--------------------------------------------------------------------------------------\r
2175 void CDXUTDialog::ClearRadioButtonGroup( UINT nButtonGroup )\r
2176 {\r
2177     // Find all radio buttons with the given group number\r
2178     for( int i = 0; i < m_Controls.GetSize(); i++ )\r
2179     {\r
2180         CDXUTControl* pControl = m_Controls.GetAt( i );\r
2181 \r
2182         if( pControl->GetType() == DXUT_CONTROL_RADIOBUTTON )\r
2183         {\r
2184             CDXUTRadioButton* pRadioButton = ( CDXUTRadioButton* )pControl;\r
2185 \r
2186             if( pRadioButton->GetButtonGroup() == nButtonGroup )\r
2187                 pRadioButton->SetChecked( false, false );\r
2188         }\r
2189     }\r
2190 }\r
2191 \r
2192 \r
2193 \r
2194 //--------------------------------------------------------------------------------------\r
2195 void CDXUTDialog::ClearComboBox( int ID )\r
2196 {\r
2197     CDXUTComboBox* pComboBox = GetComboBox( ID );\r
2198     if( pComboBox == NULL )\r
2199         return;\r
2200 \r
2201     pComboBox->RemoveAllItems();\r
2202 }\r
2203 \r
2204 \r
2205 \r
2206 \r
2207 //--------------------------------------------------------------------------------------\r
2208 void CDXUTDialog::RequestFocus( CDXUTControl* pControl )\r
2209 {\r
2210     if( s_pControlFocus == pControl )\r
2211         return;\r
2212 \r
2213     if( !pControl->CanHaveFocus() )\r
2214         return;\r
2215 \r
2216     if( s_pControlFocus )\r
2217         s_pControlFocus->OnFocusOut();\r
2218 \r
2219     pControl->OnFocusIn();\r
2220     s_pControlFocus = pControl;\r
2221 }\r
2222 \r
2223 \r
2224 //--------------------------------------------------------------------------------------\r
2225 HRESULT CDXUTDialog::DrawRect( RECT* pRect, D3DCOLOR color )\r
2226 {\r
2227     if( m_pManager->GetD3D9Device() )\r
2228         return DrawRect9( pRect, color );\r
2229     return E_FAIL;\r
2230 }\r
2231 \r
2232 \r
2233 //--------------------------------------------------------------------------------------\r
2234 HRESULT CDXUTDialog::DrawRect9( RECT* pRect, D3DCOLOR color )\r
2235 {\r
2236     RECT rcScreen = *pRect;\r
2237     OffsetRect( &rcScreen, m_x, m_y );\r
2238 \r
2239     // If caption is enabled, offset the Y position by its height.\r
2240     if( m_bCaption )\r
2241         OffsetRect( &rcScreen, 0, m_nCaptionHeight );\r
2242 \r
2243     DXUT_SCREEN_VERTEX vertices[4] =\r
2244     {\r
2245         ( float )rcScreen.left - 0.5f,  ( float )rcScreen.top - 0.5f,    0.5f, 1.0f, color, 0, 0,\r
2246         ( float )rcScreen.right - 0.5f, ( float )rcScreen.top - 0.5f,    0.5f, 1.0f, color, 0, 0,\r
2247         ( float )rcScreen.right - 0.5f, ( float )rcScreen.bottom - 0.5f, 0.5f, 1.0f, color, 0, 0,\r
2248         ( float )rcScreen.left - 0.5f,  ( float )rcScreen.bottom - 0.5f, 0.5f, 1.0f, color, 0, 0,\r
2249     };\r
2250 \r
2251     IDirect3DDevice9* pd3dDevice = m_pManager->GetD3D9Device();\r
2252 \r
2253     // Since we're doing our own drawing here we need to flush the sprites\r
2254     m_pManager->m_pSprite->Flush();\r
2255     IDirect3DVertexDeclaration9* pDecl = NULL;\r
2256     pd3dDevice->GetVertexDeclaration( &pDecl );  // Preserve the sprite's current vertex decl\r
2257     pd3dDevice->SetFVF( DXUT_SCREEN_VERTEX::FVF );\r
2258 \r
2259     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );\r
2260     pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );\r
2261 \r
2262     pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vertices, sizeof( DXUT_SCREEN_VERTEX ) );\r
2263 \r
2264     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );\r
2265     pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );\r
2266 \r
2267     // Restore the vertex decl\r
2268     pd3dDevice->SetVertexDeclaration( pDecl );\r
2269     pDecl->Release();\r
2270 \r
2271     return S_OK;\r
2272 }\r
2273 \r
2274 \r
2275 //--------------------------------------------------------------------------------------\r
2276 HRESULT CDXUTDialog::DrawPolyLine( POINT* apPoints, UINT nNumPoints, D3DCOLOR color )\r
2277 {\r
2278     DXUT_SCREEN_VERTEX* vertices = new DXUT_SCREEN_VERTEX[ nNumPoints ];\r
2279     if( vertices == NULL )\r
2280         return E_OUTOFMEMORY;\r
2281 \r
2282     DXUT_SCREEN_VERTEX* pVertex = vertices;\r
2283     POINT* pt = apPoints;\r
2284     for( UINT i = 0; i < nNumPoints; i++ )\r
2285     {\r
2286         pVertex->x = m_x + ( float )pt->x;\r
2287         pVertex->y = m_y + ( float )pt->y;\r
2288         pVertex->z = 0.5f;\r
2289         pVertex->h = 1.0f;\r
2290         pVertex->color = color;\r
2291         pVertex->tu = 0.0f;\r
2292         pVertex->tv = 0.0f;\r
2293 \r
2294         pVertex++;\r
2295         pt++;\r
2296     }\r
2297 \r
2298     IDirect3DDevice9* pd3dDevice = m_pManager->GetD3D9Device();\r
2299 \r
2300     // Since we're doing our own drawing here we need to flush the sprites\r
2301     m_pManager->m_pSprite->Flush();\r
2302     IDirect3DVertexDeclaration9* pDecl = NULL;\r
2303     pd3dDevice->GetVertexDeclaration( &pDecl );  // Preserve the sprite's current vertex decl\r
2304     pd3dDevice->SetFVF( DXUT_SCREEN_VERTEX::FVF );\r
2305 \r
2306     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );\r
2307     pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );\r
2308 \r
2309     pd3dDevice->DrawPrimitiveUP( D3DPT_LINESTRIP, nNumPoints - 1, vertices, sizeof( DXUT_SCREEN_VERTEX ) );\r
2310 \r
2311     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );\r
2312     pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );\r
2313 \r
2314     // Restore the vertex decl\r
2315     pd3dDevice->SetVertexDeclaration( pDecl );\r
2316     pDecl->Release();\r
2317 \r
2318     SAFE_DELETE_ARRAY( vertices );\r
2319     return S_OK;\r
2320 }\r
2321 \r
2322 \r
2323 //--------------------------------------------------------------------------------------\r
2324 HRESULT CDXUTDialog::DrawSprite( CDXUTElement* pElement, RECT* prcDest, float fDepth )\r
2325 {\r
2326     if( m_pManager->GetD3D9Device() )\r
2327         return DrawSprite9( pElement, prcDest );\r
2328     else\r
2329         return DrawSprite11( pElement, prcDest, fDepth );\r
2330 }\r
2331 \r
2332 \r
2333 //--------------------------------------------------------------------------------------\r
2334 HRESULT CDXUTDialog::DrawSprite9( CDXUTElement* pElement, RECT* prcDest )\r
2335 {\r
2336     // No need to draw fully transparent layers\r
2337     if( pElement->TextureColor.Current.a == 0 )\r
2338         return S_OK;\r
2339 \r
2340     RECT rcTexture = pElement->rcTexture;\r
2341 \r
2342     RECT rcScreen = *prcDest;\r
2343     OffsetRect( &rcScreen, m_x, m_y );\r
2344 \r
2345     // If caption is enabled, offset the Y position by its height.\r
2346     if( m_bCaption )\r
2347         OffsetRect( &rcScreen, 0, m_nCaptionHeight );\r
2348 \r
2349     DXUTTextureNode* pTextureNode = GetTexture( pElement->iTexture );\r
2350     if( pTextureNode == NULL )\r
2351         return E_FAIL;\r
2352 \r
2353     float fScaleX = ( float )RectWidth( rcScreen ) / RectWidth( rcTexture );\r
2354     float fScaleY = ( float )RectHeight( rcScreen ) / RectHeight( rcTexture );\r
2355 \r
2356     D3DXMATRIXA16 matTransform;\r
2357     D3DXMatrixScaling( &matTransform, fScaleX, fScaleY, 1.0f );\r
2358 \r
2359     m_pManager->m_pSprite->SetTransform( &matTransform );\r
2360 \r
2361     D3DXVECTOR3 vPos( ( float )rcScreen.left, ( float )rcScreen.top, 0.0f );\r
2362 \r
2363     vPos.x /= fScaleX;\r
2364     vPos.y /= fScaleY;\r
2365 \r
2366     return m_pManager->m_pSprite->Draw( pTextureNode->pTexture9, &rcTexture, NULL, &vPos,\r
2367                                         pElement->TextureColor.Current );\r
2368 }\r
2369 \r
2370 //--------------------------------------------------------------------------------------\r
2371 HRESULT CDXUTDialog::DrawSprite11( CDXUTElement* pElement, RECT* prcDest, float fDepth )\r
2372 {\r
2373     // No need to draw fully transparent layers\r
2374     if( pElement->TextureColor.Current.a == 0 )\r
2375         return S_OK;\r
2376 \r
2377     RECT rcTexture = pElement->rcTexture;\r
2378 \r
2379     RECT rcScreen = *prcDest;\r
2380     OffsetRect( &rcScreen, m_x, m_y );\r
2381 \r
2382     // If caption is enabled, offset the Y position by its height.\r
2383     if( m_bCaption )\r
2384         OffsetRect( &rcScreen, 0, m_nCaptionHeight );\r
2385 \r
2386     DXUTTextureNode* pTextureNode = GetTexture( pElement->iTexture );\r
2387     if( pTextureNode == NULL )\r
2388         return E_FAIL;\r
2389 \r
2390     float fBBWidth = ( float )m_pManager->m_nBackBufferWidth;\r
2391     float fBBHeight = ( float )m_pManager->m_nBackBufferHeight;\r
2392     float fTexWidth = ( float )pTextureNode->dwWidth;\r
2393     float fTexHeight = ( float )pTextureNode->dwHeight;\r
2394 \r
2395     float fRectLeft = rcScreen.left / fBBWidth;\r
2396     float fRectTop = 1.0f - rcScreen.top / fBBHeight;\r
2397     float fRectRight = rcScreen.right / fBBWidth;\r
2398     float fRectBottom = 1.0f - rcScreen.bottom / fBBHeight;\r
2399 \r
2400     fRectLeft = fRectLeft * 2.0f - 1.0f;\r
2401     fRectTop = fRectTop * 2.0f - 1.0f;\r
2402     fRectRight = fRectRight * 2.0f - 1.0f;\r
2403     fRectBottom = fRectBottom * 2.0f - 1.0f;\r
2404     \r
2405     float fTexLeft = rcTexture.left / fTexWidth;\r
2406     float fTexTop = rcTexture.top / fTexHeight;\r
2407     float fTexRight = rcTexture.right / fTexWidth;\r
2408     float fTexBottom = rcTexture.bottom / fTexHeight;\r
2409 \r
2410     // Add 6 sprite vertices\r
2411     DXUTSpriteVertex SpriteVertex;\r
2412 \r
2413     // tri1\r
2414     SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectTop, fDepth );\r
2415     SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexTop );\r
2416     SpriteVertex.vColor = pElement->TextureColor.Current;\r
2417     m_pManager->m_SpriteVertices.Add( SpriteVertex );\r
2418 \r
2419     SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectTop, fDepth );\r
2420     SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexTop );\r
2421     SpriteVertex.vColor = pElement->TextureColor.Current;\r
2422     m_pManager->m_SpriteVertices.Add( SpriteVertex );\r
2423 \r
2424     SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectBottom, fDepth );\r
2425     SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexBottom );\r
2426     SpriteVertex.vColor = pElement->TextureColor.Current;\r
2427     m_pManager->m_SpriteVertices.Add( SpriteVertex );\r
2428 \r
2429     // tri2\r
2430     SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectTop, fDepth );\r
2431     SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexTop );\r
2432     SpriteVertex.vColor = pElement->TextureColor.Current;\r
2433     m_pManager->m_SpriteVertices.Add( SpriteVertex );\r
2434 \r
2435     SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectBottom, fDepth );\r
2436     SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexBottom );\r
2437     SpriteVertex.vColor = pElement->TextureColor.Current;\r
2438     m_pManager->m_SpriteVertices.Add( SpriteVertex );\r
2439 \r
2440     SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectBottom, fDepth );\r
2441     SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexBottom );\r
2442     SpriteVertex.vColor = pElement->TextureColor.Current;\r
2443     m_pManager->m_SpriteVertices.Add( SpriteVertex );\r
2444 \r
2445     // TODO:  Why are we drawing the sprite every time?  This is very inefficient, but the sprite workaround doesn't have support for sorting now, so we have to\r
2446     // draw a sprite every time to keep the order correct between sprites and text.\r
2447     m_pManager->EndSprites11( DXUTGetD3D11Device(), DXUTGetD3D11DeviceContext() );\r
2448 \r
2449     return S_OK;\r
2450 }\r
2451 \r
2452 \r
2453 //--------------------------------------------------------------------------------------\r
2454 HRESULT CDXUTDialog::CalcTextRect( LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, int nCount )\r
2455 {\r
2456     HRESULT hr = S_OK;\r
2457 \r
2458     DXUTFontNode* pFontNode = GetFont( pElement->iFont );\r
2459     if( pFontNode == NULL )\r
2460         return E_FAIL;\r
2461 \r
2462     DWORD dwTextFormat = pElement->dwTextFormat | DT_CALCRECT;\r
2463     // Since we are only computing the rectangle, we don't need a sprite.\r
2464     if( pFontNode->pFont9 )\r
2465     {\r
2466         hr = pFontNode->pFont9->DrawText( NULL, strText, nCount, prcDest, dwTextFormat, pElement->FontColor.Current );\r
2467         if( FAILED( hr ) )\r
2468             return hr;\r
2469     }\r
2470 \r
2471     return S_OK;\r
2472 }\r
2473 \r
2474 \r
2475 //--------------------------------------------------------------------------------------\r
2476 HRESULT CDXUTDialog::DrawText( LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, bool bShadow, int nCount, bool bCenter   )\r
2477 {\r
2478     if( m_pManager->GetD3D9Device() )\r
2479         return DrawText9( strText, pElement, prcDest, bShadow, nCount );\r
2480     else\r
2481         return DrawText11( m_pManager->GetD3D11Device(), m_pManager->GetD3D11DeviceContext(), strText, pElement, prcDest, bShadow, nCount, bCenter );\r
2482 }\r
2483 \r
2484 \r
2485 //--------------------------------------------------------------------------------------\r
2486 HRESULT CDXUTDialog::DrawText9( LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, bool bShadow, int nCount )\r
2487 {\r
2488     HRESULT hr = S_OK;\r
2489 \r
2490     // No need to draw fully transparent layers\r
2491     if( pElement->FontColor.Current.a == 0 )\r
2492         return S_OK;\r
2493 \r
2494     RECT rcScreen = *prcDest;\r
2495     OffsetRect( &rcScreen, m_x, m_y );\r
2496 \r
2497     // If caption is enabled, offset the Y position by its height.\r
2498     if( m_bCaption )\r
2499         OffsetRect( &rcScreen, 0, m_nCaptionHeight );\r
2500 \r
2501     D3DXMATRIX matTransform;\r
2502     D3DXMatrixIdentity( &matTransform );\r
2503     m_pManager->m_pSprite->SetTransform( &matTransform );\r
2504 \r
2505     DXUTFontNode* pFontNode = GetFont( pElement->iFont );\r
2506 \r
2507     if( bShadow )\r
2508     {\r
2509         RECT rcShadow = rcScreen;\r
2510         OffsetRect( &rcShadow, 1, 1 );\r
2511         hr = pFontNode->pFont9->DrawText( m_pManager->m_pSprite, strText, nCount, &rcShadow, pElement->dwTextFormat,\r
2512                                           D3DCOLOR_ARGB( DWORD( pElement->FontColor.Current.a * 255 ), 0, 0, 0 ) );\r
2513         if( FAILED( hr ) )\r
2514             return hr;\r
2515     }\r
2516 \r
2517     hr = pFontNode->pFont9->DrawText( m_pManager->m_pSprite, strText, nCount, &rcScreen, pElement->dwTextFormat,\r
2518                                       pElement->FontColor.Current );\r
2519     if( FAILED( hr ) )\r
2520         return hr;\r
2521 \r
2522     return S_OK;\r
2523 }\r
2524 \r
2525 ID3D11Buffer* g_pFontBuffer11 = NULL;\r
2526 UINT g_FontBufferBytes11 = 0;\r
2527 CGrowableArray<DXUTSpriteVertex> g_FontVertices;\r
2528 ID3D11ShaderResourceView* g_pFont11 = NULL;\r
2529 ID3D11InputLayout* g_pInputLayout11 = NULL;\r
2530 HRESULT InitFont11( ID3D11Device* pd3d11Device, ID3D11InputLayout* pInputLayout )\r
2531 {\r
2532     HRESULT hr = S_OK;\r
2533     WCHAR str[MAX_PATH];\r
2534     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"UI\\Font.dds" ) );\r
2535     \r
2536     if (pd3d11Device->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0 ) {\r
2537 \r
2538         D3DX11_IMAGE_INFO dii;\r
2539         D3DX11GetImageInfoFromFile( str, NULL, &dii, NULL );\r
2540 \r
2541         D3DX11_IMAGE_LOAD_INFO dili;\r
2542         dili.BindFlags = D3DX11_DEFAULT;\r
2543         dili.CpuAccessFlags = D3DX11_DEFAULT;\r
2544         dili.Depth = D3DX11_DEFAULT;\r
2545         dili.Filter = D3DX11_DEFAULT;\r
2546         dili.FirstMipLevel = 0;\r
2547         dili.Format = DXGI_FORMAT_R8G8B8A8_UNORM;\r
2548         dili.Height = D3DX11_DEFAULT;\r
2549         dili.MipFilter = D3DX11_DEFAULT;\r
2550         dili.MipLevels = 1;\r
2551         dili.MiscFlags = D3DX11_DEFAULT;\r
2552         dili.pSrcInfo = &dii;\r
2553         dili.Usage = D3D11_USAGE_DEFAULT ;\r
2554         dili.Width = D3DX11_DEFAULT;\r
2555 \r
2556         V_RETURN( D3DX11CreateShaderResourceViewFromFile( pd3d11Device, str, &dili, NULL, &g_pFont11, &hr) );\r
2557     } else {\r
2558         V_RETURN( D3DX11CreateShaderResourceViewFromFile( pd3d11Device, str, NULL, NULL, &g_pFont11, &hr) );\r
2559     \r
2560     }\r
2561 \r
2562 \r
2563     g_pInputLayout11 = pInputLayout;\r
2564     return hr;\r
2565 }\r
2566 \r
2567 void EndFont11()\r
2568 {\r
2569     SAFE_RELEASE( g_pFontBuffer11 );\r
2570     g_FontBufferBytes11 = 0;\r
2571     SAFE_RELEASE( g_pFont11 );\r
2572 }\r
2573 \r
2574 void BeginText11()\r
2575 {\r
2576     g_FontVertices.Reset();\r
2577 }\r
2578 \r
2579 void DrawText11DXUT( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext,\r
2580                  LPCWSTR strText, RECT rcScreen, D3DXCOLOR vFontColor,\r
2581                  float fBBWidth, float fBBHeight, bool bCenter )\r
2582 {\r
2583     float fCharTexSizeX = 0.010526315f;\r
2584     //float fGlyphSizeX = 14.0f / fBBWidth;\r
2585     //float fGlyphSizeY = 32.0f / fBBHeight;\r
2586     float fGlyphSizeX = 15.0f / fBBWidth;\r
2587     float fGlyphSizeY = 42.0f / fBBHeight;\r
2588 \r
2589 \r
2590     float fRectLeft = rcScreen.left / fBBWidth;\r
2591     float fRectTop = 1.0f - rcScreen.top / fBBHeight;\r
2592 \r
2593     fRectLeft = fRectLeft * 2.0f - 1.0f;\r
2594     fRectTop = fRectTop * 2.0f - 1.0f;\r
2595 \r
2596     int NumChars = (int)wcslen( strText );\r
2597     if (bCenter) {\r
2598         float fRectRight = rcScreen.right / fBBWidth;\r
2599         fRectRight = fRectRight * 2.0f - 1.0f;\r
2600         float fRectBottom = 1.0f - rcScreen.bottom / fBBHeight;\r
2601         fRectBottom = fRectBottom * 2.0f - 1.0f;\r
2602         float fcenterx = ((fRectRight - fRectLeft) - (float)NumChars*fGlyphSizeX) *0.5f;\r
2603         float fcentery = ((fRectTop - fRectBottom) - (float)1*fGlyphSizeY) *0.5f;\r
2604         fRectLeft += fcenterx ;    \r
2605         fRectTop -= fcentery;\r
2606     }\r
2607     float fOriginalLeft = fRectLeft;\r
2608     float fTexTop = 0.0f;\r
2609     float fTexBottom = 1.0f;\r
2610 \r
2611     float fDepth = 0.5f;\r
2612     for( int i=0; i<NumChars; i++ )\r
2613     {\r
2614         if( strText[i] == '\n' )\r
2615         {\r
2616             fRectLeft = fOriginalLeft;\r
2617             fRectTop -= fGlyphSizeY;\r
2618 \r
2619             continue;\r
2620         }\r
2621         else if( strText[i] < 32 || strText[i] > 126 )\r
2622         {\r
2623             continue;\r
2624         }\r
2625 \r
2626         // Add 6 sprite vertices\r
2627         DXUTSpriteVertex SpriteVertex;\r
2628         float fRectRight = fRectLeft + fGlyphSizeX;\r
2629         float fRectBottom = fRectTop - fGlyphSizeY;\r
2630         float fTexLeft = ( strText[i] - 32 ) * fCharTexSizeX;\r
2631         float fTexRight = fTexLeft + fCharTexSizeX;\r
2632 \r
2633         // tri1\r
2634         SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectTop, fDepth );\r
2635         SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexTop );\r
2636         SpriteVertex.vColor = vFontColor;\r
2637         g_FontVertices.Add( SpriteVertex );\r
2638 \r
2639         SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectTop, fDepth );\r
2640         SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexTop );\r
2641         SpriteVertex.vColor = vFontColor;\r
2642         g_FontVertices.Add( SpriteVertex );\r
2643 \r
2644         SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectBottom, fDepth );\r
2645         SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexBottom );\r
2646         SpriteVertex.vColor = vFontColor;\r
2647         g_FontVertices.Add( SpriteVertex );\r
2648 \r
2649         // tri2\r
2650         SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectTop, fDepth );\r
2651         SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexTop );\r
2652         SpriteVertex.vColor = vFontColor;\r
2653         g_FontVertices.Add( SpriteVertex );\r
2654 \r
2655         SpriteVertex.vPos = D3DXVECTOR3( fRectRight, fRectBottom, fDepth );\r
2656         SpriteVertex.vTex = D3DXVECTOR2( fTexRight, fTexBottom );\r
2657         SpriteVertex.vColor = vFontColor;\r
2658         g_FontVertices.Add( SpriteVertex );\r
2659 \r
2660         SpriteVertex.vPos = D3DXVECTOR3( fRectLeft, fRectBottom, fDepth );\r
2661         SpriteVertex.vTex = D3DXVECTOR2( fTexLeft, fTexBottom );\r
2662         SpriteVertex.vColor = vFontColor;\r
2663         g_FontVertices.Add( SpriteVertex );\r
2664 \r
2665         fRectLeft += fGlyphSizeX;\r
2666 \r
2667     }\r
2668 \r
2669     // TODO: We have to end text after every line so that rendering order between sprites and fonts is preserved\r
2670     EndText11( pd3dDevice, pd3d11DeviceContext );\r
2671 }\r
2672 \r
2673 void EndText11( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext )\r
2674 {\r
2675 \r
2676     // ensure our buffer size can hold our sprites\r
2677     UINT FontDataBytes = g_FontVertices.GetSize() * sizeof( DXUTSpriteVertex );\r
2678     if( g_FontBufferBytes11 < FontDataBytes )\r
2679     {\r
2680         SAFE_RELEASE( g_pFontBuffer11 );\r
2681         g_FontBufferBytes11 = FontDataBytes;\r
2682 \r
2683         D3D11_BUFFER_DESC BufferDesc;\r
2684         BufferDesc.ByteWidth = g_FontBufferBytes11;\r
2685         BufferDesc.Usage = D3D11_USAGE_DYNAMIC;\r
2686         BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;\r
2687         BufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;\r
2688         BufferDesc.MiscFlags = 0;\r
2689 \r
2690         pd3dDevice->CreateBuffer( &BufferDesc, NULL, &g_pFontBuffer11 );\r
2691     }\r
2692 \r
2693     // Copy the sprites over\r
2694     D3D11_BOX destRegion;\r
2695     destRegion.left = 0;\r
2696     destRegion.right = FontDataBytes;\r
2697     destRegion.top = 0;\r
2698     destRegion.bottom = 1;\r
2699     destRegion.front = 0;\r
2700     destRegion.back = 1;\r
2701     D3D11_MAPPED_SUBRESOURCE MappedResource;\r
2702     if ( S_OK == pd3d11DeviceContext->Map( g_pFontBuffer11, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ) { \r
2703         CopyMemory( MappedResource.pData, (void*)g_FontVertices.GetData(), FontDataBytes );\r
2704         pd3d11DeviceContext->Unmap(g_pFontBuffer11, 0);\r
2705     }\r
2706 \r
2707     ID3D11ShaderResourceView* pOldTexture = NULL;\r
2708     pd3d11DeviceContext->PSGetShaderResources( 0, 1, &pOldTexture );\r
2709     pd3d11DeviceContext->PSSetShaderResources( 0, 1, &g_pFont11 );\r
2710 \r
2711     // Draw\r
2712     UINT Stride = sizeof( DXUTSpriteVertex );\r
2713     UINT Offset = 0;\r
2714     pd3d11DeviceContext->IASetVertexBuffers( 0, 1, &g_pFontBuffer11, &Stride, &Offset );\r
2715     pd3d11DeviceContext->IASetInputLayout( g_pInputLayout11 );\r
2716     pd3d11DeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );\r
2717     pd3d11DeviceContext->Draw( g_FontVertices.GetSize(), 0 );\r
2718 \r
2719     pd3d11DeviceContext->PSSetShaderResources( 0, 1, &pOldTexture );\r
2720     SAFE_RELEASE( pOldTexture );\r
2721 \r
2722     g_FontVertices.Reset();\r
2723 }\r
2724 \r
2725 //--------------------------------------------------------------------------------------\r
2726 HRESULT CDXUTDialog::DrawText11( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3d11DeviceContext,\r
2727                                  LPCWSTR strText, CDXUTElement* pElement, RECT* prcDest, bool bShadow, int nCount, bool bCenter  )\r
2728 {\r
2729     //HRESULT hr = S_OK;\r
2730 \r
2731     // No need to draw fully transparent layers\r
2732     if( pElement->FontColor.Current.a == 0 )\r
2733         return S_OK;\r
2734 \r
2735     RECT rcScreen = *prcDest;\r
2736     OffsetRect( &rcScreen, m_x, m_y);\r
2737 \r
2738     // If caption is enabled, offset the Y position by its height.\r
2739     if( m_bCaption )\r
2740         OffsetRect( &rcScreen, 0, m_nCaptionHeight );\r
2741 \r
2742     float fBBWidth = ( float )m_pManager->m_nBackBufferWidth;\r
2743     float fBBHeight = ( float )m_pManager->m_nBackBufferHeight;\r
2744 \r
2745     if( bShadow )\r
2746     {\r
2747         RECT rcShadow = rcScreen;\r
2748         OffsetRect( &rcShadow, 1, 1 );\r
2749 \r
2750         D3DXCOLOR vShadowColor( 0,0,0, 1.0f );\r
2751         DrawText11DXUT( pd3dDevice, pd3d11DeviceContext,\r
2752                  strText, rcShadow, vShadowColor,\r
2753                  fBBWidth, fBBHeight, bCenter );\r
2754 \r
2755     }\r
2756 \r
2757     D3DXCOLOR vFontColor( pElement->FontColor.Current.r, pElement->FontColor.Current.g, pElement->FontColor.Current.b, 1.0f );\r
2758     DrawText11DXUT( pd3dDevice, pd3d11DeviceContext,\r
2759              strText, rcScreen, vFontColor,\r
2760              fBBWidth, fBBHeight, bCenter );\r
2761 \r
2762     return S_OK;\r
2763 }\r
2764 \r
2765 \r
2766 //--------------------------------------------------------------------------------------\r
2767 void CDXUTDialog::SetBackgroundColors( D3DCOLOR colorTopLeft, D3DCOLOR colorTopRight, D3DCOLOR colorBottomLeft,\r
2768                                        D3DCOLOR colorBottomRight )\r
2769 {\r
2770     m_colorTopLeft = colorTopLeft;\r
2771     m_colorTopRight = colorTopRight;\r
2772     m_colorBottomLeft = colorBottomLeft;\r
2773     m_colorBottomRight = colorBottomRight;\r
2774 }\r
2775 \r
2776 \r
2777 //--------------------------------------------------------------------------------------\r
2778 void CDXUTDialog::SetNextDialog( CDXUTDialog* pNextDialog )\r
2779 {\r
2780     if( pNextDialog == NULL )\r
2781         pNextDialog = this;\r
2782 \r
2783     m_pNextDialog = pNextDialog;\r
2784     if( pNextDialog )\r
2785         m_pNextDialog->m_pPrevDialog = this;\r
2786 }\r
2787 \r
2788 \r
2789 //--------------------------------------------------------------------------------------\r
2790 void CDXUTDialog::ClearFocus()\r
2791 {\r
2792     if( s_pControlFocus )\r
2793     {\r
2794         s_pControlFocus->OnFocusOut();\r
2795         s_pControlFocus = NULL;\r
2796     }\r
2797 \r
2798     ReleaseCapture();\r
2799 }\r
2800 \r
2801 \r
2802 //--------------------------------------------------------------------------------------\r
2803 void CDXUTDialog::FocusDefaultControl()\r
2804 {\r
2805     // Check for default control in this dialog\r
2806     for( int i = 0; i < m_Controls.GetSize(); i++ )\r
2807     {\r
2808         CDXUTControl* pControl = m_Controls.GetAt( i );\r
2809         if( pControl->m_bIsDefault )\r
2810         {\r
2811             // Remove focus from the current control\r
2812             ClearFocus();\r
2813 \r
2814             // Give focus to the default control\r
2815             s_pControlFocus = pControl;\r
2816             s_pControlFocus->OnFocusIn();\r
2817             return;\r
2818         }\r
2819     }\r
2820 }\r
2821 \r
2822 \r
2823 //--------------------------------------------------------------------------------------\r
2824 bool CDXUTDialog::OnCycleFocus( bool bForward )\r
2825 {\r
2826     CDXUTControl* pControl = NULL;\r
2827     CDXUTDialog* pDialog = NULL; // pDialog and pLastDialog are used to track wrapping of\r
2828     CDXUTDialog* pLastDialog;    // focus from first control to last or vice versa.\r
2829 \r
2830     if( s_pControlFocus == NULL )\r
2831     {\r
2832         // If s_pControlFocus is NULL, we focus the first control of first dialog in\r
2833         // the case that bForward is true, and focus the last control of last dialog when\r
2834         // bForward is false.\r
2835         //\r
2836         if( bForward )\r
2837         {\r
2838             // Search for the first control from the start of the dialog\r
2839             // array.\r
2840             for( int d = 0; d < m_pManager->m_Dialogs.GetSize(); ++d )\r
2841             {\r
2842                 pDialog = pLastDialog = m_pManager->m_Dialogs.GetAt( d );\r
2843                 if( pDialog && pDialog->m_Controls.GetSize() > 0 )\r
2844                 {\r
2845                     pControl = pDialog->m_Controls.GetAt( 0 );\r
2846                     break;\r
2847                 }\r
2848             }\r
2849 \r
2850             if( !pDialog || !pControl )\r
2851             {\r
2852                 // No dialog has been registered yet or no controls have been\r
2853                 // added to the dialogs. Cannot proceed.\r
2854                 return true;\r
2855             }\r
2856         }\r
2857         else\r
2858         {\r
2859             // Search for the first control from the end of the dialog\r
2860             // array.\r
2861             for( int d = m_pManager->m_Dialogs.GetSize() - 1; d >= 0; --d )\r
2862             {\r
2863                 pDialog = pLastDialog = m_pManager->m_Dialogs.GetAt( d );\r
2864                 if( pDialog && pDialog->m_Controls.GetSize() > 0 )\r
2865                 {\r
2866                     pControl = pDialog->m_Controls.GetAt( pDialog->m_Controls.GetSize() - 1 );\r
2867                     break;\r
2868                 }\r
2869             }\r
2870 \r
2871             if( !pDialog || !pControl )\r
2872             {\r
2873                 // No dialog has been registered yet or no controls have been\r
2874                 // added to the dialogs. Cannot proceed.\r
2875                 return true;\r
2876             }\r
2877         }\r
2878     }\r
2879     else if( s_pControlFocus->m_pDialog != this )\r
2880     {\r
2881         // If a control belonging to another dialog has focus, let that other\r
2882         // dialog handle this event by returning false.\r
2883         //\r
2884         return false;\r
2885     }\r
2886     else\r
2887     {\r
2888         // Focused control belongs to this dialog. Cycle to the\r
2889         // next/previous control.\r
2890         pLastDialog = s_pControlFocus->m_pDialog;\r
2891         pControl = ( bForward ) ? GetNextControl( s_pControlFocus ) : GetPrevControl( s_pControlFocus );\r
2892         pDialog = pControl->m_pDialog;\r
2893     }\r
2894 \r
2895     for( int i = 0; i < 0xffff; i++ )\r
2896     {\r
2897         // If we just wrapped from last control to first or vice versa,\r
2898         // set the focused control to NULL. This state, where no control\r
2899         // has focus, allows the camera to work.\r
2900         int nLastDialogIndex = m_pManager->m_Dialogs.IndexOf( pLastDialog );\r
2901         int nDialogIndex = m_pManager->m_Dialogs.IndexOf( pDialog );\r
2902         if( ( !bForward && nLastDialogIndex < nDialogIndex ) ||\r
2903             ( bForward && nDialogIndex < nLastDialogIndex ) )\r
2904         {\r
2905             if( s_pControlFocus )\r
2906                 s_pControlFocus->OnFocusOut();\r
2907             s_pControlFocus = NULL;\r
2908             return true;\r
2909         }\r
2910 \r
2911         // If we've gone in a full circle then focus doesn't change\r
2912         if( pControl == s_pControlFocus )\r
2913             return true;\r
2914 \r
2915         // If the dialog accepts keybord input and the control can have focus then\r
2916         // move focus\r
2917         if( pControl->m_pDialog->m_bKeyboardInput && pControl->CanHaveFocus() )\r
2918         {\r
2919             if( s_pControlFocus )\r
2920                 s_pControlFocus->OnFocusOut();\r
2921             s_pControlFocus = pControl;\r
2922             s_pControlFocus->OnFocusIn();\r
2923             return true;\r
2924         }\r
2925 \r
2926         pLastDialog = pDialog;\r
2927         pControl = ( bForward ) ? GetNextControl( pControl ) : GetPrevControl( pControl );\r
2928         pDialog = pControl->m_pDialog;\r
2929     }\r
2930 \r
2931     // If we reached this point, the chain of dialogs didn't form a complete loop\r
2932     DXTRACE_ERR( L"CDXUTDialog: Multiple dialogs are improperly chained together", E_FAIL );\r
2933     return false;\r
2934 }\r
2935 \r
2936 \r
2937 //--------------------------------------------------------------------------------------\r
2938 HRESULT CDXUTDialogResourceManager::CreateFont9( UINT iFont )\r
2939 {\r
2940     HRESULT hr = S_OK;\r
2941 \r
2942     DXUTFontNode* pFontNode = m_FontCache.GetAt( iFont );\r
2943 \r
2944     SAFE_RELEASE( pFontNode->pFont9 );\r
2945 \r
2946     V_RETURN( D3DXCreateFont( m_pd3d9Device, pFontNode->nHeight, 0, pFontNode->nWeight, 1, FALSE, DEFAULT_CHARSET,\r
2947                               OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,\r
2948                               pFontNode->strFace, &pFontNode->pFont9 ) );\r
2949 \r
2950     return S_OK;\r
2951 }\r
2952 \r
2953 \r
2954 \r
2955 //--------------------------------------------------------------------------------------\r
2956 HRESULT CDXUTDialogResourceManager::CreateFont11( UINT iFont )\r
2957 {\r
2958     return S_OK;\r
2959 }\r
2960 \r
2961 \r
2962 //--------------------------------------------------------------------------------------\r
2963 HRESULT CDXUTDialogResourceManager::CreateTexture9( UINT iTexture )\r
2964 {\r
2965     HRESULT hr = S_OK;\r
2966 \r
2967     DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( iTexture );\r
2968 \r
2969 \r
2970     D3DXIMAGE_INFO info;\r
2971 \r
2972     if( !pTextureNode->bFileSource )\r
2973     {\r
2974         if( pTextureNode->nResourceID == 0xFFFF && pTextureNode->hResourceModule == ( HMODULE )0xFFFF )\r
2975         {\r
2976             hr = DXUTCreateGUITextureFromInternalArray9( m_pd3d9Device, &pTextureNode->pTexture9, &info );\r
2977             if( FAILED( hr ) )\r
2978                 return DXTRACE_ERR( L"D3DXCreateTextureFromFileInMemoryEx", hr );\r
2979         }\r
2980         else\r
2981         {\r
2982             LPCWSTR pID = pTextureNode->nResourceID ? ( LPCWSTR )( size_t )pTextureNode->nResourceID :\r
2983                 pTextureNode->strFilename;\r
2984 \r
2985             // Create texture from resource\r
2986             hr = D3DXCreateTextureFromResourceEx( m_pd3d9Device, pTextureNode->hResourceModule, pID, D3DX_DEFAULT,\r
2987                                                   D3DX_DEFAULT,\r
2988                                                   1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,\r
2989                                                   D3DX_DEFAULT, D3DX_DEFAULT, 0,\r
2990                                                   &info, NULL, &pTextureNode->pTexture9 );\r
2991             if( FAILED( hr ) )\r
2992                 return DXTRACE_ERR( L"D3DXCreateTextureFromResourceEx", hr );\r
2993         }\r
2994     }\r
2995     else\r
2996     {\r
2997         // Make sure there's a texture to create\r
2998         if( pTextureNode->strFilename[0] == 0 )\r
2999             return S_OK;\r
3000 \r
3001         // Create texture from file\r
3002         hr = D3DXCreateTextureFromFileEx( m_pd3d9Device, pTextureNode->strFilename, D3DX_DEFAULT, D3DX_DEFAULT,\r
3003                                           1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,\r
3004                                           D3DX_DEFAULT, D3DX_DEFAULT, 0,\r
3005                                           &info, NULL, &pTextureNode->pTexture9 );\r
3006         if( FAILED( hr ) )\r
3007         {\r
3008             return DXTRACE_ERR( L"D3DXCreateTextureFromFileEx", hr );\r
3009         }\r
3010     }\r
3011 \r
3012     // Store dimensions\r
3013     pTextureNode->dwWidth = info.Width;\r
3014     pTextureNode->dwHeight = info.Height;\r
3015 \r
3016     return S_OK;\r
3017 }\r
3018 \r
3019 \r
3020 //--------------------------------------------------------------------------------------\r
3021 HRESULT CDXUTDialogResourceManager::CreateTexture11( UINT iTexture )\r
3022 {\r
3023     HRESULT hr = S_OK;\r
3024 \r
3025     DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( iTexture );\r
3026 \r
3027     if( !pTextureNode->bFileSource )\r
3028     {\r
3029         if( pTextureNode->nResourceID == 0xFFFF && pTextureNode->hResourceModule == ( HMODULE )0xFFFF )\r
3030         {\r
3031             hr = DXUTCreateGUITextureFromInternalArray11( m_pd3d11Device, &pTextureNode->pTexture11, NULL );\r
3032             if( FAILED( hr ) )\r
3033                 return DXTRACE_ERR( L"D3DX10CreateResourceFromFileInMemory", hr );\r
3034         }\r
3035         //else\r
3036         //{\r
3037         //    LPCWSTR pID = pTextureNode->nResourceID ? ( LPCWSTR )( size_t )pTextureNode->nResourceID :\r
3038         //        pTextureNode->strFilename;\r
3039 \r
3040         //    D3DX10_IMAGE_INFO SrcInfo;\r
3041         //    D3DX10GetImageInfoFromResource( NULL, pID, NULL, &SrcInfo, NULL );\r
3042 \r
3043         //    // Create texture from resource\r
3044         //    ID3D10Resource* pRes;\r
3045         //    D3DX10_IMAGE_LOAD_INFO loadInfo;\r
3046         //    loadInfo.Width = D3DX10_DEFAULT;\r
3047         //    loadInfo.Height = D3DX10_DEFAULT;\r
3048         //    loadInfo.Depth = D3DX10_DEFAULT;\r
3049         //    loadInfo.FirstMipLevel = 0;\r
3050         //    loadInfo.MipLevels = 1;\r
3051         //    loadInfo.Usage = D3D10_USAGE_DEFAULT;\r
3052         //    loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;\r
3053         //    loadInfo.CpuAccessFlags = 0;\r
3054         //    loadInfo.MiscFlags = 0;\r
3055         //    loadInfo.Format = MAKE_TYPELESS( SrcInfo.Format );\r
3056         //    loadInfo.Filter = D3DX10_FILTER_NONE;\r
3057         //    loadInfo.MipFilter = D3DX10_FILTER_NONE;\r
3058         //    loadInfo.pSrcInfo = &SrcInfo;\r
3059 \r
3060         //    hr = D3DX10CreateTextureFromResource( m_pd3d10Device, pTextureNode->hResourceModule, pID, &loadInfo,\r
3061         //                                          NULL, &pRes, NULL );\r
3062         //    if( FAILED( hr ) )\r
3063         //        return DXTRACE_ERR( L"D3DX10CreateResourceFromResource", hr );\r
3064         //    hr = pRes->QueryInterface( __uuidof( ID3D10Texture2D ), ( LPVOID* )&pTextureNode->pTexture10 );\r
3065         //    SAFE_RELEASE( pRes );\r
3066         //    if( FAILED( hr ) )\r
3067         //        return hr;\r
3068         //}\r
3069     }\r
3070     else\r
3071     {\r
3072         //\r
3073         //// Make sure there's a texture to create\r
3074         //if( pTextureNode->strFilename[0] == 0 )\r
3075         //    return S_OK;\r
3076 \r
3077         //D3DX10_IMAGE_INFO SrcInfo;\r
3078         //D3DX10GetImageInfoFromFile( pTextureNode->strFilename, NULL, &SrcInfo, NULL );\r
3079 \r
3080         //// Create texture from file\r
3081         //ID3D10Resource* pRes;\r
3082         //D3DX10_IMAGE_LOAD_INFO loadInfo;\r
3083         //loadInfo.Width = D3DX10_DEFAULT;\r
3084         //loadInfo.Height = D3DX10_DEFAULT;\r
3085         //loadInfo.Depth = D3DX10_DEFAULT;\r
3086         //loadInfo.FirstMipLevel = 0;\r
3087         //loadInfo.MipLevels = 1;\r
3088         //loadInfo.Usage = D3D10_USAGE_DEFAULT;\r
3089         //loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE;\r
3090         //loadInfo.CpuAccessFlags = 0;\r
3091         //loadInfo.MiscFlags = 0;\r
3092         //loadInfo.Format = MAKE_TYPELESS( SrcInfo.Format );\r
3093         //loadInfo.Filter = D3DX10_FILTER_NONE;\r
3094         //loadInfo.MipFilter = D3DX10_FILTER_NONE;\r
3095         //loadInfo.pSrcInfo = &SrcInfo;\r
3096         //hr = D3DX10CreateTextureFromFile( m_pd3d10Device, pTextureNode->strFilename, &loadInfo, NULL, &pRes, NULL );\r
3097         //if( FAILED( hr ) )\r
3098         //{\r
3099         //    return DXTRACE_ERR( L"D3DX10CreateResourceFromFileEx", hr );\r
3100         //}\r
3101         //hr = pRes->QueryInterface( __uuidof( ID3D10Texture2D ), ( LPVOID* )&pTextureNode->pTexture10 );\r
3102         //SAFE_RELEASE( pRes );\r
3103         //if( FAILED( hr ) )\r
3104         //    return hr;\r
3105         //\r
3106     }\r
3107 \r
3108     // Store dimensions\r
3109     D3D11_TEXTURE2D_DESC desc;\r
3110     pTextureNode->pTexture11->GetDesc( &desc );\r
3111     pTextureNode->dwWidth = desc.Width;\r
3112     pTextureNode->dwHeight = desc.Height;\r
3113 \r
3114     // Create resource view\r
3115     D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;\r
3116     SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;\r
3117     SRVDesc.Format = MAKE_SRGB( desc.Format );\r
3118     SRVDesc.Texture2D.MipLevels = 1;\r
3119     SRVDesc.Texture2D.MostDetailedMip = 0;\r
3120     hr = m_pd3d11Device->CreateShaderResourceView( pTextureNode->pTexture11, &SRVDesc, &pTextureNode->pTexResView11 );\r
3121 \r
3122     return hr;\r
3123 }\r
3124 \r
3125 \r
3126 //--------------------------------------------------------------------------------------\r
3127 void CDXUTDialog::InitDefaultElements()\r
3128 {\r
3129     SetFont( 0, L"Arial", 14, FW_NORMAL );\r
3130 \r
3131     CDXUTElement Element;\r
3132     RECT rcTexture;\r
3133 \r
3134     //-------------------------------------\r
3135     // Element for the caption\r
3136     //-------------------------------------\r
3137     m_CapElement.SetFont( 0 );\r
3138     SetRect( &rcTexture, 17, 269, 241, 287 );\r
3139     m_CapElement.SetTexture( 0, &rcTexture );\r
3140     m_CapElement.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 255, 255, 255, 255 );\r
3141     m_CapElement.FontColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 255, 255, 255, 255 );\r
3142     m_CapElement.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_VCENTER );\r
3143     // Pre-blend as we don't need to transition the state\r
3144     m_CapElement.TextureColor.Blend( DXUT_STATE_NORMAL, 10.0f );\r
3145     m_CapElement.FontColor.Blend( DXUT_STATE_NORMAL, 10.0f );\r
3146 \r
3147     //-------------------------------------\r
3148     // CDXUTStatic\r
3149     //-------------------------------------\r
3150     Element.SetFont( 0 );\r
3151     Element.FontColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 200, 200, 200, 200 );\r
3152 \r
3153     // Assign the Element\r
3154     SetDefaultElement( DXUT_CONTROL_STATIC, 0, &Element );\r
3155 \r
3156 \r
3157     //-------------------------------------\r
3158     // CDXUTButton - Button\r
3159     //-------------------------------------\r
3160     SetRect( &rcTexture, 0, 0, 136, 54 );\r
3161     Element.SetTexture( 0, &rcTexture );\r
3162     Element.SetFont( 0 );\r
3163     Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 );\r
3164     Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 200, 255, 255, 255 );\r
3165     Element.FontColor.States[ DXUT_STATE_MOUSEOVER ] = D3DCOLOR_ARGB( 255, 0, 0, 0 );\r
3166 \r
3167     // Assign the Element\r
3168     SetDefaultElement( DXUT_CONTROL_BUTTON, 0, &Element );\r
3169 \r
3170 \r
3171     //-------------------------------------\r
3172     // CDXUTButton - Fill layer\r
3173     //-------------------------------------\r
3174     SetRect( &rcTexture, 136, 0, 252, 54 );\r
3175     Element.SetTexture( 0, &rcTexture, D3DCOLOR_ARGB( 0, 255, 255, 255 ) );\r
3176     Element.TextureColor.States[ DXUT_STATE_MOUSEOVER ] = D3DCOLOR_ARGB( 160, 255, 255, 255 );\r
3177     Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 60, 0, 0, 0 );\r
3178     Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 30, 255, 255, 255 );\r
3179 \r
3180 \r
3181     // Assign the Element\r
3182     SetDefaultElement( DXUT_CONTROL_BUTTON, 1, &Element );\r
3183 \r
3184 \r
3185     //-------------------------------------\r
3186     // CDXUTCheckBox - Box\r
3187     //-------------------------------------\r
3188     SetRect( &rcTexture, 0, 54, 27, 81 );\r
3189     Element.SetTexture( 0, &rcTexture );\r
3190     Element.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_VCENTER );\r
3191     Element.FontColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 200, 200, 200, 200 );\r
3192     Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 );\r
3193     Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 200, 255, 255, 255 );\r
3194     Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 255, 255, 255, 255 );\r
3195 \r
3196     // Assign the Element\r
3197     SetDefaultElement( DXUT_CONTROL_CHECKBOX, 0, &Element );\r
3198 \r
3199 \r
3200     //-------------------------------------\r
3201     // CDXUTCheckBox - Check\r
3202     //-------------------------------------\r
3203     SetRect( &rcTexture, 27, 54, 54, 81 );\r
3204     Element.SetTexture( 0, &rcTexture );\r
3205 \r
3206     // Assign the Element\r
3207     SetDefaultElement( DXUT_CONTROL_CHECKBOX, 1, &Element );\r
3208 \r
3209 \r
3210     //-------------------------------------\r
3211     // CDXUTRadioButton - Box\r
3212     //-------------------------------------\r
3213     SetRect( &rcTexture, 54, 54, 81, 81 );\r
3214     Element.SetTexture( 0, &rcTexture );\r
3215     Element.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_VCENTER );\r
3216     Element.FontColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 200, 200, 200, 200 );\r
3217     Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 );\r
3218     Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 200, 255, 255, 255 );\r
3219     Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 255, 255, 255, 255 );\r
3220 \r
3221     // Assign the Element\r
3222     SetDefaultElement( DXUT_CONTROL_RADIOBUTTON, 0, &Element );\r
3223 \r
3224 \r
3225     //-------------------------------------\r
3226     // CDXUTRadioButton - Check\r
3227     //-------------------------------------\r
3228     SetRect( &rcTexture, 81, 54, 108, 81 );\r
3229     Element.SetTexture( 0, &rcTexture );\r
3230 \r
3231     // Assign the Element\r
3232     SetDefaultElement( DXUT_CONTROL_RADIOBUTTON, 1, &Element );\r
3233 \r
3234 \r
3235     //-------------------------------------\r
3236     // CDXUTComboBox - Main\r
3237     //-------------------------------------\r
3238     SetRect( &rcTexture, 7, 81, 247, 123 );\r
3239     Element.SetTexture( 0, &rcTexture );\r
3240     Element.SetFont( 0 );\r
3241     Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 200, 200, 200 );\r
3242     Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 170, 230, 230, 230 );\r
3243     Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 70, 200, 200, 200 );\r
3244     Element.FontColor.States[ DXUT_STATE_MOUSEOVER ] = D3DCOLOR_ARGB( 255, 0, 0, 0 );\r
3245     Element.FontColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 255, 0, 0, 0 );\r
3246     Element.FontColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 200, 200, 200, 200 );\r
3247 \r
3248 \r
3249     // Assign the Element\r
3250     SetDefaultElement( DXUT_CONTROL_COMBOBOX, 0, &Element );\r
3251 \r
3252 \r
3253     //-------------------------------------\r
3254     // CDXUTComboBox - Button\r
3255     //-------------------------------------\r
3256     SetRect( &rcTexture, 98, 189, 151, 238 );\r
3257     Element.SetTexture( 0, &rcTexture );\r
3258     Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 );\r
3259     Element.TextureColor.States[ DXUT_STATE_PRESSED ] = D3DCOLOR_ARGB( 255, 150, 150, 150 );\r
3260     Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 200, 255, 255, 255 );\r
3261     Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 70, 255, 255, 255 );\r
3262 \r
3263     // Assign the Element\r
3264     SetDefaultElement( DXUT_CONTROL_COMBOBOX, 1, &Element );\r
3265 \r
3266 \r
3267     //-------------------------------------\r
3268     // CDXUTComboBox - Dropdown\r
3269     //-------------------------------------\r
3270     SetRect( &rcTexture, 13, 123, 241, 160 );\r
3271     Element.SetTexture( 0, &rcTexture );\r
3272     Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_LEFT | DT_TOP );\r
3273 \r
3274     // Assign the Element\r
3275     SetDefaultElement( DXUT_CONTROL_COMBOBOX, 2, &Element );\r
3276 \r
3277 \r
3278     //-------------------------------------\r
3279     // CDXUTComboBox - Selection\r
3280     //-------------------------------------\r
3281     SetRect( &rcTexture, 12, 163, 239, 183 );\r
3282     Element.SetTexture( 0, &rcTexture );\r
3283     Element.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_TOP );\r
3284 \r
3285     // Assign the Element\r
3286     SetDefaultElement( DXUT_CONTROL_COMBOBOX, 3, &Element );\r
3287 \r
3288 \r
3289     //-------------------------------------\r
3290     // CDXUTSlider - Track\r
3291     //-------------------------------------\r
3292     SetRect( &rcTexture, 1, 187, 93, 228 );\r
3293     Element.SetTexture( 0, &rcTexture );\r
3294     Element.TextureColor.States[ DXUT_STATE_NORMAL ] = D3DCOLOR_ARGB( 150, 255, 255, 255 );\r
3295     Element.TextureColor.States[ DXUT_STATE_FOCUS ] = D3DCOLOR_ARGB( 200, 255, 255, 255 );\r
3296     Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 70, 255, 255, 255 );\r
3297 \r
3298     // Assign the Element\r
3299     SetDefaultElement( DXUT_CONTROL_SLIDER, 0, &Element );\r
3300 \r
3301     //-------------------------------------\r
3302     // CDXUTSlider - Button\r
3303     //-------------------------------------\r
3304     SetRect( &rcTexture, 151, 193, 192, 234 );\r
3305     Element.SetTexture( 0, &rcTexture );\r
3306 \r
3307     // Assign the Element\r
3308     SetDefaultElement( DXUT_CONTROL_SLIDER, 1, &Element );\r
3309 \r
3310     //-------------------------------------\r
3311     // CDXUTScrollBar - Track\r
3312     //-------------------------------------\r
3313     int nScrollBarStartX = 196;\r
3314     int nScrollBarStartY = 191;\r
3315     SetRect( &rcTexture, nScrollBarStartX + 0, nScrollBarStartY + 21, nScrollBarStartX + 22, nScrollBarStartY + 32 );\r
3316     Element.SetTexture( 0, &rcTexture );\r
3317     Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 255, 200, 200, 200 );\r
3318 \r
3319     // Assign the Element\r
3320     SetDefaultElement( DXUT_CONTROL_SCROLLBAR, 0, &Element );\r
3321 \r
3322     //-------------------------------------\r
3323     // CDXUTScrollBar - Up Arrow\r
3324     //-------------------------------------\r
3325     SetRect( &rcTexture, nScrollBarStartX + 0, nScrollBarStartY + 1, nScrollBarStartX + 22, nScrollBarStartY + 21 );\r
3326     Element.SetTexture( 0, &rcTexture );\r
3327     Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 255, 200, 200, 200 );\r
3328 \r
3329 \r
3330     // Assign the Element\r
3331     SetDefaultElement( DXUT_CONTROL_SCROLLBAR, 1, &Element );\r
3332 \r
3333     //-------------------------------------\r
3334     // CDXUTScrollBar - Down Arrow\r
3335     //-------------------------------------\r
3336     SetRect( &rcTexture, nScrollBarStartX + 0, nScrollBarStartY + 32, nScrollBarStartX + 22, nScrollBarStartY + 53 );\r
3337     Element.SetTexture( 0, &rcTexture );\r
3338     Element.TextureColor.States[ DXUT_STATE_DISABLED ] = D3DCOLOR_ARGB( 255, 200, 200, 200 );\r
3339 \r
3340 \r
3341     // Assign the Element\r
3342     SetDefaultElement( DXUT_CONTROL_SCROLLBAR, 2, &Element );\r
3343 \r
3344     //-------------------------------------\r
3345     // CDXUTScrollBar - Button\r
3346     //-------------------------------------\r
3347     SetRect( &rcTexture, 220, 192, 238, 234 );\r
3348     Element.SetTexture( 0, &rcTexture );\r
3349 \r
3350     // Assign the Element\r
3351     SetDefaultElement( DXUT_CONTROL_SCROLLBAR, 3, &Element );\r
3352 \r
3353 \r
3354     //-------------------------------------\r
3355     // CDXUTEditBox\r
3356     //-------------------------------------\r
3357     // Element assignment:\r
3358     //   0 - text area\r
3359     //   1 - top left border\r
3360     //   2 - top border\r
3361     //   3 - top right border\r
3362     //   4 - left border\r
3363     //   5 - right border\r
3364     //   6 - lower left border\r
3365     //   7 - lower border\r
3366     //   8 - lower right border\r
3367 \r
3368     Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_LEFT | DT_TOP );\r
3369 \r
3370     // Assign the style\r
3371     SetRect( &rcTexture, 14, 90, 241, 113 );\r
3372     Element.SetTexture( 0, &rcTexture );\r
3373     SetDefaultElement( DXUT_CONTROL_EDITBOX, 0, &Element );\r
3374     SetRect( &rcTexture, 8, 82, 14, 90 );\r
3375     Element.SetTexture( 0, &rcTexture );\r
3376     SetDefaultElement( DXUT_CONTROL_EDITBOX, 1, &Element );\r
3377     SetRect( &rcTexture, 14, 82, 241, 90 );\r
3378     Element.SetTexture( 0, &rcTexture );\r
3379     SetDefaultElement( DXUT_CONTROL_EDITBOX, 2, &Element );\r
3380     SetRect( &rcTexture, 241, 82, 246, 90 );\r
3381     Element.SetTexture( 0, &rcTexture );\r
3382     SetDefaultElement( DXUT_CONTROL_EDITBOX, 3, &Element );\r
3383     SetRect( &rcTexture, 8, 90, 14, 113 );\r
3384     Element.SetTexture( 0, &rcTexture );\r
3385     SetDefaultElement( DXUT_CONTROL_EDITBOX, 4, &Element );\r
3386     SetRect( &rcTexture, 241, 90, 246, 113 );\r
3387     Element.SetTexture( 0, &rcTexture );\r
3388     SetDefaultElement( DXUT_CONTROL_EDITBOX, 5, &Element );\r
3389     SetRect( &rcTexture, 8, 113, 14, 121 );\r
3390     Element.SetTexture( 0, &rcTexture );\r
3391     SetDefaultElement( DXUT_CONTROL_EDITBOX, 6, &Element );\r
3392     SetRect( &rcTexture, 14, 113, 241, 121 );\r
3393     Element.SetTexture( 0, &rcTexture );\r
3394     SetDefaultElement( DXUT_CONTROL_EDITBOX, 7, &Element );\r
3395     SetRect( &rcTexture, 241, 113, 246, 121 );\r
3396     Element.SetTexture( 0, &rcTexture );\r
3397     SetDefaultElement( DXUT_CONTROL_EDITBOX, 8, &Element );\r
3398 \r
3399     //-------------------------------------\r
3400     // CDXUTListBox - Main\r
3401     //-------------------------------------\r
3402     SetRect( &rcTexture, 13, 123, 241, 160 );\r
3403     Element.SetTexture( 0, &rcTexture );\r
3404     Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_LEFT | DT_TOP );\r
3405 \r
3406     // Assign the Element\r
3407     SetDefaultElement( DXUT_CONTROL_LISTBOX, 0, &Element );\r
3408 \r
3409     //-------------------------------------\r
3410     // CDXUTListBox - Selection\r
3411     //-------------------------------------\r
3412 \r
3413     SetRect( &rcTexture, 16, 166, 240, 183 );\r
3414     Element.SetTexture( 0, &rcTexture );\r
3415     Element.SetFont( 0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), DT_LEFT | DT_TOP );\r
3416 \r
3417     // Assign the Element\r
3418     SetDefaultElement( DXUT_CONTROL_LISTBOX, 1, &Element );\r
3419 }\r
3420 \r
3421 \r
3422 \r
3423 //--------------------------------------------------------------------------------------\r
3424 // CDXUTControl class\r
3425 //--------------------------------------------------------------------------------------\r
3426 \r
3427 //--------------------------------------------------------------------------------------\r
3428 CDXUTControl::CDXUTControl( CDXUTDialog* pDialog )\r
3429 {\r
3430     m_Type = DXUT_CONTROL_BUTTON;\r
3431     m_pDialog = pDialog;\r
3432     m_ID = 0;\r
3433     m_Index = 0;\r
3434     m_pUserData = NULL;\r
3435 \r
3436     m_bEnabled = true;\r
3437     m_bVisible = true;\r
3438     m_bMouseOver = false;\r
3439     m_bHasFocus = false;\r
3440     m_bIsDefault = false;\r
3441 \r
3442     m_pDialog = NULL;\r
3443 \r
3444     m_x = 0;\r
3445     m_y = 0;\r
3446     m_width = 0;\r
3447     m_height = 0;\r
3448 \r
3449     ZeroMemory( &m_rcBoundingBox, sizeof( m_rcBoundingBox ) );\r
3450 }\r
3451 \r
3452 \r
3453 CDXUTControl::~CDXUTControl()\r
3454 {\r
3455     for( int i = 0; i < m_Elements.GetSize(); ++i )\r
3456     {\r
3457         delete m_Elements[i];\r
3458     }\r
3459     m_Elements.RemoveAll();\r
3460 }\r
3461 \r
3462 \r
3463 //--------------------------------------------------------------------------------------\r
3464 void CDXUTControl::SetTextColor( D3DCOLOR Color )\r
3465 {\r
3466     CDXUTElement* pElement = m_Elements.GetAt( 0 );\r
3467 \r
3468     if( pElement )\r
3469         pElement->FontColor.States[DXUT_STATE_NORMAL] = Color;\r
3470 }\r
3471 \r
3472 \r
3473 //--------------------------------------------------------------------------------------\r
3474 HRESULT CDXUTControl::SetElement( UINT iElement, CDXUTElement* pElement )\r
3475 {\r
3476     HRESULT hr = S_OK;\r
3477 \r
3478     if( pElement == NULL )\r
3479         return E_INVALIDARG;\r
3480 \r
3481     // Make certain the array is this large\r
3482     for( UINT i = m_Elements.GetSize(); i <= iElement; i++ )\r
3483     {\r
3484         CDXUTElement* pNewElement = new CDXUTElement();\r
3485         if( pNewElement == NULL )\r
3486             return E_OUTOFMEMORY;\r
3487 \r
3488         hr = m_Elements.Add( pNewElement );\r
3489         if( FAILED( hr ) )\r
3490         {\r
3491             SAFE_DELETE( pNewElement );\r
3492             return hr;\r
3493         }\r
3494     }\r
3495 \r
3496     // Update the data\r
3497     CDXUTElement* pCurElement = m_Elements.GetAt( iElement );\r
3498     *pCurElement = *pElement;\r
3499 \r
3500     return S_OK;\r
3501 }\r
3502 \r
3503 \r
3504 //--------------------------------------------------------------------------------------\r
3505 void CDXUTControl::Refresh()\r
3506 {\r
3507     m_bMouseOver = false;\r
3508     m_bHasFocus = false;\r
3509 \r
3510     for( int i = 0; i < m_Elements.GetSize(); i++ )\r
3511     {\r
3512         CDXUTElement* pElement = m_Elements.GetAt( i );\r
3513         pElement->Refresh();\r
3514     }\r
3515 }\r
3516 \r
3517 \r
3518 //--------------------------------------------------------------------------------------\r
3519 void CDXUTControl::UpdateRects()\r
3520 {\r
3521     SetRect( &m_rcBoundingBox, m_x, m_y, m_x + m_width, m_y + m_height );\r
3522 }\r
3523 \r
3524 \r
3525 //--------------------------------------------------------------------------------------\r
3526 // CDXUTStatic class\r
3527 //--------------------------------------------------------------------------------------\r
3528 \r
3529 //--------------------------------------------------------------------------------------\r
3530 CDXUTStatic::CDXUTStatic( CDXUTDialog* pDialog )\r
3531 {\r
3532     m_Type = DXUT_CONTROL_STATIC;\r
3533     m_pDialog = pDialog;\r
3534 \r
3535     ZeroMemory( &m_strText, sizeof( m_strText ) );\r
3536 \r
3537     for( int i = 0; i < m_Elements.GetSize(); i++ )\r
3538     {\r
3539         CDXUTElement* pElement = m_Elements.GetAt( i );\r
3540         SAFE_DELETE( pElement );\r
3541     }\r
3542 \r
3543     m_Elements.RemoveAll();\r
3544 }\r
3545 \r
3546 \r
3547 //--------------------------------------------------------------------------------------\r
3548 void CDXUTStatic::Render( float fElapsedTime )\r
3549 {\r
3550     if( m_bVisible == false )\r
3551         return;\r
3552 \r
3553     DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL;\r
3554 \r
3555     if( m_bEnabled == false )\r
3556         iState = DXUT_STATE_DISABLED;\r
3557 \r
3558     CDXUTElement* pElement = m_Elements.GetAt( 0 );\r
3559 \r
3560     pElement->FontColor.Blend( iState, fElapsedTime );\r
3561 \r
3562     m_pDialog->DrawText( m_strText, pElement, &m_rcBoundingBox, false, -1, false);\r
3563 }\r
3564 \r
3565 \r
3566 //--------------------------------------------------------------------------------------\r
3567 HRESULT CDXUTStatic::GetTextCopy( __out_ecount(bufferCount) LPWSTR strDest, \r
3568                                   UINT bufferCount )\r
3569 {\r
3570     // Validate incoming parameters\r
3571     if( strDest == NULL || bufferCount == 0 )\r
3572     {\r
3573         return E_INVALIDARG;\r
3574     }\r
3575 \r
3576     // Copy the window text\r
3577     wcscpy_s( strDest, bufferCount, m_strText );\r
3578 \r
3579     return S_OK;\r
3580 }\r
3581 \r
3582 \r
3583 //--------------------------------------------------------------------------------------\r
3584 HRESULT CDXUTStatic::SetText( LPCWSTR strText )\r
3585 {\r
3586     if( strText == NULL )\r
3587     {\r
3588         m_strText[0] = 0;\r
3589         return S_OK;\r
3590     }\r
3591 \r
3592     wcscpy_s( m_strText, MAX_PATH, strText );\r
3593     return S_OK;\r
3594 }\r
3595 \r
3596 \r
3597 //--------------------------------------------------------------------------------------\r
3598 // CDXUTButton class\r
3599 //--------------------------------------------------------------------------------------\r
3600 \r
3601 //--------------------------------------------------------------------------------------\r
3602 CDXUTButton::CDXUTButton( CDXUTDialog* pDialog )\r
3603 {\r
3604     m_Type = DXUT_CONTROL_BUTTON;\r
3605     m_pDialog = pDialog;\r
3606 \r
3607     m_bPressed = false;\r
3608     m_nHotkey = 0;\r
3609 }\r
3610 \r
3611 //--------------------------------------------------------------------------------------\r
3612 bool CDXUTButton::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
3613 {\r
3614     if( !m_bEnabled || !m_bVisible )\r
3615         return false;\r
3616 \r
3617     switch( uMsg )\r
3618     {\r
3619         case WM_KEYDOWN:\r
3620         {\r
3621             switch( wParam )\r
3622             {\r
3623                 case VK_SPACE:\r
3624                     m_bPressed = true;\r
3625                     return true;\r
3626             }\r
3627         }\r
3628 \r
3629         case WM_KEYUP:\r
3630         {\r
3631             switch( wParam )\r
3632             {\r
3633                 case VK_SPACE:\r
3634                     if( m_bPressed == true )\r
3635                     {\r
3636                         m_bPressed = false;\r
3637                         m_pDialog->SendEvent( EVENT_BUTTON_CLICKED, true, this );\r
3638                     }\r
3639                     return true;\r
3640             }\r
3641         }\r
3642     }\r
3643     return false;\r
3644 }\r
3645 \r
3646 \r
3647 //--------------------------------------------------------------------------------------\r
3648 bool CDXUTButton::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam )\r
3649 {\r
3650     if( !m_bEnabled || !m_bVisible )\r
3651         return false;\r
3652 \r
3653     switch( uMsg )\r
3654     {\r
3655         case WM_LBUTTONDOWN:\r
3656         case WM_LBUTTONDBLCLK:\r
3657             {\r
3658                 if( ContainsPoint( pt ) )\r
3659                 {\r
3660                     // Pressed while inside the control\r
3661                     m_bPressed = true;\r
3662                     SetCapture( DXUTGetHWND() );\r
3663 \r
3664                     if( !m_bHasFocus )\r
3665                         m_pDialog->RequestFocus( this );\r
3666 \r
3667                     return true;\r
3668                 }\r
3669 \r
3670                 break;\r
3671             }\r
3672 \r
3673         case WM_LBUTTONUP:\r
3674         {\r
3675             if( m_bPressed )\r
3676             {\r
3677                 m_bPressed = false;\r
3678                 ReleaseCapture();\r
3679 \r
3680                 if( !m_pDialog->m_bKeyboardInput )\r
3681                     m_pDialog->ClearFocus();\r
3682 \r
3683                 // Button click\r
3684                 if( ContainsPoint( pt ) )\r
3685                     m_pDialog->SendEvent( EVENT_BUTTON_CLICKED, true, this );\r
3686 \r
3687                 return true;\r
3688             }\r
3689 \r
3690             break;\r
3691         }\r
3692     };\r
3693 \r
3694     return false;\r
3695 }\r
3696 \r
3697 //--------------------------------------------------------------------------------------\r
3698 void CDXUTButton::Render( float fElapsedTime )\r
3699 {\r
3700     if( m_bVisible == false )\r
3701         return;\r
3702 \r
3703     int nOffsetX = 0;\r
3704     int nOffsetY = 0;\r
3705 \r
3706     DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL;\r
3707 \r
3708     if( m_bVisible == false )\r
3709     {\r
3710         iState = DXUT_STATE_HIDDEN;\r
3711     }\r
3712     else if( m_bEnabled == false )\r
3713     {\r
3714         iState = DXUT_STATE_DISABLED;\r
3715     }\r
3716     else if( m_bPressed )\r
3717     {\r
3718         iState = DXUT_STATE_PRESSED;\r
3719 \r
3720         nOffsetX = 1;\r
3721         nOffsetY = 2;\r
3722     }\r
3723     else if( m_bMouseOver )\r
3724     {\r
3725         iState = DXUT_STATE_MOUSEOVER;\r
3726 \r
3727         nOffsetX = -1;\r
3728         nOffsetY = -2;\r
3729     }\r
3730     else if( m_bHasFocus )\r
3731     {\r
3732         iState = DXUT_STATE_FOCUS;\r
3733     }\r
3734 \r
3735     // Background fill layer\r
3736     //TODO: remove magic numbers\r
3737     CDXUTElement* pElement = m_Elements.GetAt( 0 );\r
3738 \r
3739     float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f;\r
3740 \r
3741     RECT rcWindow = m_rcBoundingBox;\r
3742     OffsetRect( &rcWindow, nOffsetX, nOffsetY );\r
3743 \r
3744 \r
3745     // Blend current color\r
3746     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
3747     pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate );\r
3748 \r
3749     m_pDialog->DrawSprite( pElement, &rcWindow, DXUT_FAR_BUTTON_DEPTH );\r
3750     m_pDialog->DrawText( m_strText, pElement, &rcWindow, false, -1, true );\r
3751 \r
3752     // Main button\r
3753     pElement = m_Elements.GetAt( 1 );\r
3754 \r
3755     // Blend current color\r
3756     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
3757     pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate );\r
3758 \r
3759     m_pDialog->DrawSprite( pElement, &rcWindow, DXUT_NEAR_BUTTON_DEPTH );\r
3760     m_pDialog->DrawText( m_strText, pElement, &rcWindow, false, -1, true );\r
3761 }\r
3762 \r
3763 \r
3764 \r
3765 //--------------------------------------------------------------------------------------\r
3766 // CDXUTCheckBox class\r
3767 //--------------------------------------------------------------------------------------\r
3768 \r
3769 //--------------------------------------------------------------------------------------\r
3770 CDXUTCheckBox::CDXUTCheckBox( CDXUTDialog* pDialog )\r
3771 {\r
3772     m_Type = DXUT_CONTROL_CHECKBOX;\r
3773     m_pDialog = pDialog;\r
3774 \r
3775     m_bChecked = false;\r
3776 }\r
3777 \r
3778 \r
3779 //--------------------------------------------------------------------------------------\r
3780 bool CDXUTCheckBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
3781 {\r
3782     if( !m_bEnabled || !m_bVisible )\r
3783         return false;\r
3784 \r
3785     switch( uMsg )\r
3786     {\r
3787         case WM_KEYDOWN:\r
3788         {\r
3789             switch( wParam )\r
3790             {\r
3791                 case VK_SPACE:\r
3792                     m_bPressed = true;\r
3793                     return true;\r
3794             }\r
3795         }\r
3796 \r
3797         case WM_KEYUP:\r
3798         {\r
3799             switch( wParam )\r
3800             {\r
3801                 case VK_SPACE:\r
3802                     if( m_bPressed == true )\r
3803                     {\r
3804                         m_bPressed = false;\r
3805                         SetCheckedInternal( !m_bChecked, true );\r
3806                     }\r
3807                     return true;\r
3808             }\r
3809         }\r
3810     }\r
3811     return false;\r
3812 }\r
3813 \r
3814 \r
3815 //--------------------------------------------------------------------------------------\r
3816 bool CDXUTCheckBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam )\r
3817 {\r
3818     if( !m_bEnabled || !m_bVisible )\r
3819         return false;\r
3820 \r
3821     switch( uMsg )\r
3822     {\r
3823         case WM_LBUTTONDOWN:\r
3824         case WM_LBUTTONDBLCLK:\r
3825             {\r
3826                 if( ContainsPoint( pt ) )\r
3827                 {\r
3828                     // Pressed while inside the control\r
3829                     m_bPressed = true;\r
3830                     SetCapture( DXUTGetHWND() );\r
3831 \r
3832                     if( !m_bHasFocus )\r
3833                         m_pDialog->RequestFocus( this );\r
3834 \r
3835                     return true;\r
3836                 }\r
3837 \r
3838                 break;\r
3839             }\r
3840 \r
3841         case WM_LBUTTONUP:\r
3842         {\r
3843             if( m_bPressed )\r
3844             {\r
3845                 m_bPressed = false;\r
3846                 ReleaseCapture();\r
3847 \r
3848                 // Button click\r
3849                 if( ContainsPoint( pt ) )\r
3850                     SetCheckedInternal( !m_bChecked, true );\r
3851 \r
3852                 return true;\r
3853             }\r
3854 \r
3855             break;\r
3856         }\r
3857     };\r
3858 \r
3859     return false;\r
3860 }\r
3861 \r
3862 \r
3863 //--------------------------------------------------------------------------------------\r
3864 void CDXUTCheckBox::SetCheckedInternal( bool bChecked, bool bFromInput )\r
3865 {\r
3866     m_bChecked = bChecked;\r
3867 \r
3868     m_pDialog->SendEvent( EVENT_CHECKBOX_CHANGED, bFromInput, this );\r
3869 }\r
3870 \r
3871 \r
3872 //--------------------------------------------------------------------------------------\r
3873 BOOL CDXUTCheckBox::ContainsPoint( POINT pt )\r
3874 {\r
3875     return ( PtInRect( &m_rcBoundingBox, pt ) ||\r
3876              PtInRect( &m_rcButton, pt ) );\r
3877 }\r
3878 \r
3879 \r
3880 \r
3881 //--------------------------------------------------------------------------------------\r
3882 void CDXUTCheckBox::UpdateRects()\r
3883 {\r
3884     CDXUTButton::UpdateRects();\r
3885 \r
3886     m_rcButton = m_rcBoundingBox;\r
3887     m_rcButton.right = m_rcButton.left + RectHeight( m_rcButton );\r
3888 \r
3889     m_rcText = m_rcBoundingBox;\r
3890     m_rcText.left += ( int )( 1.25f * RectWidth( m_rcButton ) );\r
3891 }\r
3892 \r
3893 \r
3894 \r
3895 //--------------------------------------------------------------------------------------\r
3896 void CDXUTCheckBox::Render( float fElapsedTime )\r
3897 {\r
3898     if( m_bVisible == false )\r
3899         return;\r
3900     DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL;\r
3901 \r
3902     if( m_bVisible == false )\r
3903         iState = DXUT_STATE_HIDDEN;\r
3904     else if( m_bEnabled == false )\r
3905         iState = DXUT_STATE_DISABLED;\r
3906     else if( m_bPressed )\r
3907         iState = DXUT_STATE_PRESSED;\r
3908     else if( m_bMouseOver )\r
3909         iState = DXUT_STATE_MOUSEOVER;\r
3910     else if( m_bHasFocus )\r
3911         iState = DXUT_STATE_FOCUS;\r
3912 \r
3913     CDXUTElement* pElement = m_Elements.GetAt( 0 );\r
3914 \r
3915     float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f;\r
3916 \r
3917     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
3918     pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate );\r
3919 \r
3920     m_pDialog->DrawSprite( pElement, &m_rcButton, DXUT_NEAR_BUTTON_DEPTH );\r
3921     m_pDialog->DrawText( m_strText, pElement, &m_rcText, false, -1, false );\r
3922 \r
3923     if( !m_bChecked )\r
3924         iState = DXUT_STATE_HIDDEN;\r
3925 \r
3926     pElement = m_Elements.GetAt( 1 );\r
3927 \r
3928     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
3929     m_pDialog->DrawSprite( pElement, &m_rcButton, DXUT_FAR_BUTTON_DEPTH );\r
3930 }\r
3931 \r
3932 \r
3933 \r
3934 \r
3935 //--------------------------------------------------------------------------------------\r
3936 // CDXUTRadioButton class\r
3937 //--------------------------------------------------------------------------------------\r
3938 \r
3939 //--------------------------------------------------------------------------------------\r
3940 CDXUTRadioButton::CDXUTRadioButton( CDXUTDialog* pDialog )\r
3941 {\r
3942     m_Type = DXUT_CONTROL_RADIOBUTTON;\r
3943     m_pDialog = pDialog;\r
3944 }\r
3945 \r
3946 \r
3947 \r
3948 //--------------------------------------------------------------------------------------\r
3949 bool CDXUTRadioButton::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
3950 {\r
3951     if( !m_bEnabled || !m_bVisible )\r
3952         return false;\r
3953 \r
3954     switch( uMsg )\r
3955     {\r
3956         case WM_KEYDOWN:\r
3957         {\r
3958             switch( wParam )\r
3959             {\r
3960                 case VK_SPACE:\r
3961                     m_bPressed = true;\r
3962                     return true;\r
3963             }\r
3964         }\r
3965 \r
3966         case WM_KEYUP:\r
3967         {\r
3968             switch( wParam )\r
3969             {\r
3970                 case VK_SPACE:\r
3971                     if( m_bPressed == true )\r
3972                     {\r
3973                         m_bPressed = false;\r
3974 \r
3975                         m_pDialog->ClearRadioButtonGroup( m_nButtonGroup );\r
3976                         m_bChecked = !m_bChecked;\r
3977 \r
3978                         m_pDialog->SendEvent( EVENT_RADIOBUTTON_CHANGED, true, this );\r
3979                     }\r
3980                     return true;\r
3981             }\r
3982         }\r
3983     }\r
3984     return false;\r
3985 }\r
3986 \r
3987 \r
3988 //--------------------------------------------------------------------------------------\r
3989 bool CDXUTRadioButton::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam )\r
3990 {\r
3991     if( !m_bEnabled || !m_bVisible )\r
3992         return false;\r
3993 \r
3994     switch( uMsg )\r
3995     {\r
3996         case WM_LBUTTONDOWN:\r
3997         case WM_LBUTTONDBLCLK:\r
3998             {\r
3999                 if( ContainsPoint( pt ) )\r
4000                 {\r
4001                     // Pressed while inside the control\r
4002                     m_bPressed = true;\r
4003                     SetCapture( DXUTGetHWND() );\r
4004 \r
4005                     if( !m_bHasFocus )\r
4006                         m_pDialog->RequestFocus( this );\r
4007 \r
4008                     return true;\r
4009                 }\r
4010 \r
4011                 break;\r
4012             }\r
4013 \r
4014         case WM_LBUTTONUP:\r
4015         {\r
4016             if( m_bPressed )\r
4017             {\r
4018                 m_bPressed = false;\r
4019                 ReleaseCapture();\r
4020 \r
4021                 // Button click\r
4022                 if( ContainsPoint( pt ) )\r
4023                 {\r
4024                     m_pDialog->ClearRadioButtonGroup( m_nButtonGroup );\r
4025                     m_bChecked = !m_bChecked;\r
4026 \r
4027                     m_pDialog->SendEvent( EVENT_RADIOBUTTON_CHANGED, true, this );\r
4028                 }\r
4029 \r
4030                 return true;\r
4031             }\r
4032 \r
4033             break;\r
4034         }\r
4035     };\r
4036 \r
4037     return false;\r
4038 }\r
4039 \r
4040 //--------------------------------------------------------------------------------------\r
4041 void CDXUTRadioButton::SetCheckedInternal( bool bChecked, bool bClearGroup, bool bFromInput )\r
4042 {\r
4043     if( bChecked && bClearGroup )\r
4044         m_pDialog->ClearRadioButtonGroup( m_nButtonGroup );\r
4045 \r
4046     m_bChecked = bChecked;\r
4047     m_pDialog->SendEvent( EVENT_RADIOBUTTON_CHANGED, bFromInput, this );\r
4048 }\r
4049 \r
4050 \r
4051 \r
4052 \r
4053 //--------------------------------------------------------------------------------------\r
4054 // CDXUTComboBox class\r
4055 //--------------------------------------------------------------------------------------\r
4056 \r
4057 //--------------------------------------------------------------------------------------\r
4058 CDXUTComboBox::CDXUTComboBox( CDXUTDialog* pDialog ) : m_ScrollBar( pDialog )\r
4059 {\r
4060     m_Type = DXUT_CONTROL_COMBOBOX;\r
4061     m_pDialog = pDialog;\r
4062 \r
4063     m_nDropHeight = 100;\r
4064 \r
4065     m_nSBWidth = 16;\r
4066     m_bOpened = false;\r
4067     m_iSelected = -1;\r
4068     m_iFocused = -1;\r
4069 }\r
4070 \r
4071 \r
4072 //--------------------------------------------------------------------------------------\r
4073 CDXUTComboBox::~CDXUTComboBox()\r
4074 {\r
4075     RemoveAllItems();\r
4076 }\r
4077 \r
4078 \r
4079 //--------------------------------------------------------------------------------------\r
4080 void CDXUTComboBox::SetTextColor( D3DCOLOR Color )\r
4081 {\r
4082     CDXUTElement* pElement = m_Elements.GetAt( 0 );\r
4083 \r
4084     if( pElement )\r
4085         pElement->FontColor.States[DXUT_STATE_NORMAL] = Color;\r
4086 \r
4087     pElement = m_Elements.GetAt( 2 );\r
4088 \r
4089     if( pElement )\r
4090         pElement->FontColor.States[DXUT_STATE_NORMAL] = Color;\r
4091 }\r
4092 \r
4093 \r
4094 //--------------------------------------------------------------------------------------\r
4095 void CDXUTComboBox::UpdateRects()\r
4096 {\r
4097 \r
4098     CDXUTButton::UpdateRects();\r
4099 \r
4100     m_rcButton = m_rcBoundingBox;\r
4101     m_rcButton.left = m_rcButton.right - RectHeight( m_rcButton );\r
4102 \r
4103     m_rcText = m_rcBoundingBox;\r
4104     m_rcText.right = m_rcButton.left;\r
4105 \r
4106     m_rcDropdown = m_rcText;\r
4107     OffsetRect( &m_rcDropdown, 0, ( int )( 0.90f * RectHeight( m_rcText ) ) );\r
4108     m_rcDropdown.bottom += m_nDropHeight;\r
4109     m_rcDropdown.right -= m_nSBWidth;\r
4110 \r
4111     m_rcDropdownText = m_rcDropdown;\r
4112     m_rcDropdownText.left += ( int )( 0.1f * RectWidth( m_rcDropdown ) );\r
4113     m_rcDropdownText.right -= ( int )( 0.1f * RectWidth( m_rcDropdown ) );\r
4114     m_rcDropdownText.top += ( int )( 0.1f * RectHeight( m_rcDropdown ) );\r
4115     m_rcDropdownText.bottom -= ( int )( 0.1f * RectHeight( m_rcDropdown ) );\r
4116 \r
4117     // Update the scrollbar's rects\r
4118     m_ScrollBar.SetLocation( m_rcDropdown.right, m_rcDropdown.top + 2 );\r
4119     m_ScrollBar.SetSize( m_nSBWidth, RectHeight( m_rcDropdown ) - 2 );\r
4120     DXUTFontNode* pFontNode = m_pDialog->GetManager()->GetFontNode( m_Elements.GetAt( 2 )->iFont );\r
4121     if( pFontNode && pFontNode->nHeight )\r
4122     {\r
4123         m_ScrollBar.SetPageSize( RectHeight( m_rcDropdownText ) / pFontNode->nHeight );\r
4124 \r
4125         // The selected item may have been scrolled off the page.\r
4126         // Ensure that it is in page again.\r
4127         m_ScrollBar.ShowItem( m_iSelected );\r
4128     }\r
4129 }\r
4130 \r
4131 \r
4132 //--------------------------------------------------------------------------------------\r
4133 void CDXUTComboBox::OnFocusOut()\r
4134 {\r
4135     CDXUTButton::OnFocusOut();\r
4136 \r
4137     m_bOpened = false;\r
4138 }\r
4139 \r
4140 \r
4141 //--------------------------------------------------------------------------------------\r
4142 bool CDXUTComboBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
4143 {\r
4144     const DWORD REPEAT_MASK = ( 0x40000000 );\r
4145 \r
4146     if( !m_bEnabled || !m_bVisible )\r
4147         return false;\r
4148 \r
4149     // Let the scroll bar have a chance to handle it first\r
4150     if( m_ScrollBar.HandleKeyboard( uMsg, wParam, lParam ) )\r
4151         return true;\r
4152 \r
4153     switch( uMsg )\r
4154     {\r
4155         case WM_KEYDOWN:\r
4156         {\r
4157             switch( wParam )\r
4158             {\r
4159                 case VK_RETURN:\r
4160                     if( m_bOpened )\r
4161                     {\r
4162                         if( m_iSelected != m_iFocused )\r
4163                         {\r
4164                             m_iSelected = m_iFocused;\r
4165                             m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this );\r
4166                         }\r
4167                         m_bOpened = false;\r
4168 \r
4169                         if( !m_pDialog->m_bKeyboardInput )\r
4170                             m_pDialog->ClearFocus();\r
4171 \r
4172                         return true;\r
4173                     }\r
4174                     break;\r
4175 \r
4176                 case VK_F4:\r
4177                     // Filter out auto-repeats\r
4178                     if( lParam & REPEAT_MASK )\r
4179                         return true;\r
4180 \r
4181                     m_bOpened = !m_bOpened;\r
4182 \r
4183                     if( !m_bOpened )\r
4184                     {\r
4185                         m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this );\r
4186 \r
4187                         if( !m_pDialog->m_bKeyboardInput )\r
4188                             m_pDialog->ClearFocus();\r
4189                     }\r
4190 \r
4191                     return true;\r
4192 \r
4193                 case VK_LEFT:\r
4194                 case VK_UP:\r
4195                     if( m_iFocused > 0 )\r
4196                     {\r
4197                         m_iFocused--;\r
4198                         m_iSelected = m_iFocused;\r
4199 \r
4200                         if( !m_bOpened )\r
4201                             m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this );\r
4202                     }\r
4203 \r
4204                     return true;\r
4205 \r
4206                 case VK_RIGHT:\r
4207                 case VK_DOWN:\r
4208                     if( m_iFocused + 1 < ( int )GetNumItems() )\r
4209                     {\r
4210                         m_iFocused++;\r
4211                         m_iSelected = m_iFocused;\r
4212 \r
4213                         if( !m_bOpened )\r
4214                             m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this );\r
4215                     }\r
4216 \r
4217                     return true;\r
4218             }\r
4219             break;\r
4220         }\r
4221     }\r
4222 \r
4223     return false;\r
4224 }\r
4225 \r
4226 \r
4227 //--------------------------------------------------------------------------------------\r
4228 bool CDXUTComboBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam )\r
4229 {\r
4230     if( !m_bEnabled || !m_bVisible )\r
4231         return false;\r
4232 \r
4233     // Let the scroll bar handle it first.\r
4234     if( m_ScrollBar.HandleMouse( uMsg, pt, wParam, lParam ) )\r
4235         return true;\r
4236 \r
4237     switch( uMsg )\r
4238     {\r
4239         case WM_MOUSEMOVE:\r
4240         {\r
4241             if( m_bOpened && PtInRect( &m_rcDropdown, pt ) )\r
4242             {\r
4243                 // Determine which item has been selected\r
4244                 for( int i = 0; i < m_Items.GetSize(); i++ )\r
4245                 {\r
4246                     DXUTComboBoxItem* pItem = m_Items.GetAt( i );\r
4247                     if( pItem->bVisible &&\r
4248                         PtInRect( &pItem->rcActive, pt ) )\r
4249                     {\r
4250                         m_iFocused = i;\r
4251                     }\r
4252                 }\r
4253                 return true;\r
4254             }\r
4255             break;\r
4256         }\r
4257 \r
4258         case WM_LBUTTONDOWN:\r
4259         case WM_LBUTTONDBLCLK:\r
4260             {\r
4261                 if( ContainsPoint( pt ) )\r
4262                 {\r
4263                     // Pressed while inside the control\r
4264                     m_bPressed = true;\r
4265                     SetCapture( DXUTGetHWND() );\r
4266 \r
4267                     if( !m_bHasFocus )\r
4268                         m_pDialog->RequestFocus( this );\r
4269 \r
4270                     // Toggle dropdown\r
4271                     if( m_bHasFocus )\r
4272                     {\r
4273                         m_bOpened = !m_bOpened;\r
4274 \r
4275                         if( !m_bOpened )\r
4276                         {\r
4277                             if( !m_pDialog->m_bKeyboardInput )\r
4278                                 m_pDialog->ClearFocus();\r
4279                         }\r
4280                     }\r
4281 \r
4282                     return true;\r
4283                 }\r
4284 \r
4285                 // Perhaps this click is within the dropdown\r
4286                 if( m_bOpened && PtInRect( &m_rcDropdown, pt ) )\r
4287                 {\r
4288                     // Determine which item has been selected\r
4289                     for( int i = m_ScrollBar.GetTrackPos(); i < m_Items.GetSize(); i++ )\r
4290                     {\r
4291                         DXUTComboBoxItem* pItem = m_Items.GetAt( i );\r
4292                         if( pItem->bVisible &&\r
4293                             PtInRect( &pItem->rcActive, pt ) )\r
4294                         {\r
4295                             m_iFocused = m_iSelected = i;\r
4296                             m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this );\r
4297                             m_bOpened = false;\r
4298 \r
4299                             if( !m_pDialog->m_bKeyboardInput )\r
4300                                 m_pDialog->ClearFocus();\r
4301 \r
4302                             break;\r
4303                         }\r
4304                     }\r
4305 \r
4306                     return true;\r
4307                 }\r
4308 \r
4309                 // Mouse click not on main control or in dropdown, fire an event if needed\r
4310                 if( m_bOpened )\r
4311                 {\r
4312                     m_iFocused = m_iSelected;\r
4313 \r
4314                     m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this );\r
4315                     m_bOpened = false;\r
4316                 }\r
4317 \r
4318                 // Make sure the control is no longer in a pressed state\r
4319                 m_bPressed = false;\r
4320 \r
4321                 // Release focus if appropriate\r
4322                 if( !m_pDialog->m_bKeyboardInput )\r
4323                 {\r
4324                     m_pDialog->ClearFocus();\r
4325                 }\r
4326 \r
4327                 break;\r
4328             }\r
4329 \r
4330         case WM_LBUTTONUP:\r
4331         {\r
4332             if( m_bPressed && ContainsPoint( pt ) )\r
4333             {\r
4334                 // Button click\r
4335                 m_bPressed = false;\r
4336                 ReleaseCapture();\r
4337                 return true;\r
4338             }\r
4339 \r
4340             break;\r
4341         }\r
4342 \r
4343         case WM_MOUSEWHEEL:\r
4344         {\r
4345             int zDelta = ( short )HIWORD( wParam ) / WHEEL_DELTA;\r
4346             if( m_bOpened )\r
4347             {\r
4348                 UINT uLines;\r
4349                 SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &uLines, 0 );\r
4350                 m_ScrollBar.Scroll( -zDelta * uLines );\r
4351             }\r
4352             else\r
4353             {\r
4354                 if( zDelta > 0 )\r
4355                 {\r
4356                     if( m_iFocused > 0 )\r
4357                     {\r
4358                         m_iFocused--;\r
4359                         m_iSelected = m_iFocused;\r
4360 \r
4361                         if( !m_bOpened )\r
4362                             m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this );\r
4363                     }\r
4364                 }\r
4365                 else\r
4366                 {\r
4367                     if( m_iFocused + 1 < ( int )GetNumItems() )\r
4368                     {\r
4369                         m_iFocused++;\r
4370                         m_iSelected = m_iFocused;\r
4371 \r
4372                         if( !m_bOpened )\r
4373                             m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this );\r
4374                     }\r
4375                 }\r
4376             }\r
4377             return true;\r
4378         }\r
4379     };\r
4380 \r
4381     return false;\r
4382 }\r
4383 \r
4384 \r
4385 //--------------------------------------------------------------------------------------\r
4386 void CDXUTComboBox::OnHotkey()\r
4387 {\r
4388     if( m_bOpened )\r
4389         return;\r
4390 \r
4391     if( m_iSelected == -1 )\r
4392         return;\r
4393 \r
4394     if( m_pDialog->IsKeyboardInputEnabled() )\r
4395         m_pDialog->RequestFocus( this );\r
4396 \r
4397     m_iSelected++;\r
4398 \r
4399     if( m_iSelected >= ( int )m_Items.GetSize() )\r
4400         m_iSelected = 0;\r
4401 \r
4402     m_iFocused = m_iSelected;\r
4403     m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, true, this );\r
4404 }\r
4405 \r
4406 \r
4407 //--------------------------------------------------------------------------------------\r
4408 void CDXUTComboBox::Render( float fElapsedTime )\r
4409 {\r
4410     if( m_bVisible == false )\r
4411         return;\r
4412     DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL;\r
4413 \r
4414     if( !m_bOpened )\r
4415         iState = DXUT_STATE_HIDDEN;\r
4416 \r
4417     // Dropdown box\r
4418     CDXUTElement* pElement = m_Elements.GetAt( 2 );\r
4419 \r
4420     // If we have not initialized the scroll bar page size,\r
4421     // do that now.\r
4422     static bool bSBInit;\r
4423     if( !bSBInit )\r
4424     {\r
4425         // Update the page size of the scroll bar\r
4426         if( m_pDialog->GetManager()->GetFontNode( pElement->iFont )->nHeight )\r
4427             m_ScrollBar.SetPageSize( RectHeight( m_rcDropdownText ) /\r
4428                                      m_pDialog->GetManager()->GetFontNode( pElement->iFont )->nHeight );\r
4429         else\r
4430             m_ScrollBar.SetPageSize( RectHeight( m_rcDropdownText ) );\r
4431         bSBInit = true;\r
4432     }\r
4433 \r
4434     // Scroll bar\r
4435     if( m_bOpened )\r
4436         m_ScrollBar.Render( fElapsedTime );\r
4437 \r
4438     // Blend current color\r
4439     pElement->TextureColor.Blend( iState, fElapsedTime );\r
4440     pElement->FontColor.Blend( iState, fElapsedTime );\r
4441 \r
4442     m_pDialog->DrawSprite( pElement, &m_rcDropdown, DXUT_NEAR_BUTTON_DEPTH );\r
4443 \r
4444     // Selection outline\r
4445     CDXUTElement* pSelectionElement = m_Elements.GetAt( 3 );\r
4446     pSelectionElement->TextureColor.Current = pElement->TextureColor.Current;\r
4447     pSelectionElement->FontColor.Current = pSelectionElement->FontColor.States[ DXUT_STATE_NORMAL ];\r
4448 \r
4449     DXUTFontNode* pFont = m_pDialog->GetFont( pElement->iFont );\r
4450     if( pFont )\r
4451     {\r
4452         int curY = m_rcDropdownText.top;\r
4453         int nRemainingHeight = RectHeight( m_rcDropdownText );\r
4454         //WCHAR strDropdown[4096] = {0};\r
4455 \r
4456         for( int i = m_ScrollBar.GetTrackPos(); i < m_Items.GetSize(); i++ )\r
4457         {\r
4458             DXUTComboBoxItem* pItem = m_Items.GetAt( i );\r
4459 \r
4460             // Make sure there's room left in the dropdown\r
4461             nRemainingHeight -= pFont->nHeight;\r
4462             if( nRemainingHeight < 0 )\r
4463             {\r
4464                 pItem->bVisible = false;\r
4465                 continue;\r
4466             }\r
4467 \r
4468             SetRect( &pItem->rcActive, m_rcDropdownText.left, curY, m_rcDropdownText.right, curY + pFont->nHeight );\r
4469             curY += pFont->nHeight;\r
4470 \r
4471             //debug\r
4472             //int blue = 50 * i;\r
4473             //m_pDialog->DrawRect( &pItem->rcActive, 0xFFFF0000 | blue );\r
4474 \r
4475             pItem->bVisible = true;\r
4476 \r
4477             if( m_bOpened )\r
4478             {\r
4479                 if( ( int )i == m_iFocused )\r
4480                 {\r
4481                     RECT rc;\r
4482                     SetRect( &rc, m_rcDropdown.left, pItem->rcActive.top - 2, m_rcDropdown.right,\r
4483                              pItem->rcActive.bottom + 2 );\r
4484                     m_pDialog->DrawSprite( pSelectionElement, &rc, DXUT_NEAR_BUTTON_DEPTH );\r
4485                     m_pDialog->DrawText( pItem->strText, pSelectionElement, &pItem->rcActive );\r
4486                 }\r
4487                 else\r
4488                 {\r
4489                     m_pDialog->DrawText( pItem->strText, pElement, &pItem->rcActive );\r
4490                 }\r
4491             }\r
4492         }\r
4493     }\r
4494 \r
4495     int nOffsetX = 0;\r
4496     int nOffsetY = 0;\r
4497 \r
4498     iState = DXUT_STATE_NORMAL;\r
4499 \r
4500     if( m_bVisible == false )\r
4501         iState = DXUT_STATE_HIDDEN;\r
4502     else if( m_bEnabled == false )\r
4503         iState = DXUT_STATE_DISABLED;\r
4504     else if( m_bPressed )\r
4505     {\r
4506         iState = DXUT_STATE_PRESSED;\r
4507 \r
4508         nOffsetX = 1;\r
4509         nOffsetY = 2;\r
4510     }\r
4511     else if( m_bMouseOver )\r
4512     {\r
4513         iState = DXUT_STATE_MOUSEOVER;\r
4514 \r
4515         nOffsetX = -1;\r
4516         nOffsetY = -2;\r
4517     }\r
4518     else if( m_bHasFocus )\r
4519         iState = DXUT_STATE_FOCUS;\r
4520 \r
4521     float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f;\r
4522 \r
4523     // Button\r
4524     pElement = m_Elements.GetAt( 1 );\r
4525 \r
4526     // Blend current color\r
4527     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
4528 \r
4529     RECT rcWindow = m_rcButton;\r
4530     OffsetRect( &rcWindow, nOffsetX, nOffsetY );\r
4531     m_pDialog->DrawSprite( pElement, &rcWindow, DXUT_FAR_BUTTON_DEPTH );\r
4532 \r
4533     if( m_bOpened )\r
4534         iState = DXUT_STATE_PRESSED;\r
4535 \r
4536     // Main text box\r
4537     //TODO: remove magic numbers\r
4538     pElement = m_Elements.GetAt( 0 );\r
4539 \r
4540     // Blend current color\r
4541     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
4542     pElement->FontColor.Blend( iState, fElapsedTime, fBlendRate );\r
4543 \r
4544     m_pDialog->DrawSprite( pElement, &m_rcText, DXUT_NEAR_BUTTON_DEPTH );\r
4545 \r
4546     if( m_iSelected >= 0 && m_iSelected < ( int )m_Items.GetSize() )\r
4547     {\r
4548         DXUTComboBoxItem* pItem = m_Items.GetAt( m_iSelected );\r
4549         if( pItem != NULL )\r
4550         {\r
4551             m_pDialog->DrawText( pItem->strText, pElement, &m_rcText, false, -1, true );\r
4552 \r
4553         }\r
4554     }\r
4555 }\r
4556 \r
4557 \r
4558 //--------------------------------------------------------------------------------------\r
4559 HRESULT CDXUTComboBox::AddItem( const WCHAR* strText, void* pData )\r
4560 {\r
4561     // Validate parameters\r
4562     if( strText == NULL )\r
4563     {\r
4564         return E_INVALIDARG;\r
4565     }\r
4566 \r
4567     // Create a new item and set the data\r
4568     DXUTComboBoxItem* pItem = new DXUTComboBoxItem;\r
4569     if( pItem == NULL )\r
4570     {\r
4571         return DXTRACE_ERR_MSGBOX( L"new", E_OUTOFMEMORY );\r
4572     }\r
4573 \r
4574     ZeroMemory( pItem, sizeof( DXUTComboBoxItem ) );\r
4575     wcscpy_s( pItem->strText, 256, strText );\r
4576     pItem->pData = pData;\r
4577 \r
4578     m_Items.Add( pItem );\r
4579 \r
4580     // Update the scroll bar with new range\r
4581     m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() );\r
4582 \r
4583     // If this is the only item in the list, it's selected\r
4584     if( GetNumItems() == 1 )\r
4585     {\r
4586         m_iSelected = 0;\r
4587         m_iFocused = 0;\r
4588         m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, false, this );\r
4589     }\r
4590 \r
4591     return S_OK;\r
4592 }\r
4593 \r
4594 \r
4595 //--------------------------------------------------------------------------------------\r
4596 void CDXUTComboBox::RemoveItem( UINT index )\r
4597 {\r
4598     DXUTComboBoxItem* pItem = m_Items.GetAt( index );\r
4599     SAFE_DELETE( pItem );\r
4600     m_Items.Remove( index );\r
4601     m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() );\r
4602     if( m_iSelected >= m_Items.GetSize() )\r
4603         m_iSelected = m_Items.GetSize() - 1;\r
4604 }\r
4605 \r
4606 \r
4607 //--------------------------------------------------------------------------------------\r
4608 void CDXUTComboBox::RemoveAllItems()\r
4609 {\r
4610     for( int i = 0; i < m_Items.GetSize(); i++ )\r
4611     {\r
4612         DXUTComboBoxItem* pItem = m_Items.GetAt( i );\r
4613         SAFE_DELETE( pItem );\r
4614     }\r
4615 \r
4616     m_Items.RemoveAll();\r
4617     m_ScrollBar.SetTrackRange( 0, 1 );\r
4618     m_iFocused = m_iSelected = -1;\r
4619 }\r
4620 \r
4621 \r
4622 \r
4623 //--------------------------------------------------------------------------------------\r
4624 bool CDXUTComboBox::ContainsItem( const WCHAR* strText, UINT iStart )\r
4625 {\r
4626     return ( -1 != FindItem( strText, iStart ) );\r
4627 }\r
4628 \r
4629 \r
4630 //--------------------------------------------------------------------------------------\r
4631 int CDXUTComboBox::FindItem( const WCHAR* strText, UINT iStart )\r
4632 {\r
4633     if( strText == NULL )\r
4634         return -1;\r
4635 \r
4636     for( int i = iStart; i < m_Items.GetSize(); i++ )\r
4637     {\r
4638         DXUTComboBoxItem* pItem = m_Items.GetAt( i );\r
4639 \r
4640         if( 0 == wcscmp( pItem->strText, strText ) )\r
4641         {\r
4642             return i;\r
4643         }\r
4644     }\r
4645 \r
4646     return -1;\r
4647 }\r
4648 \r
4649 \r
4650 //--------------------------------------------------------------------------------------\r
4651 void* CDXUTComboBox::GetSelectedData()\r
4652 {\r
4653     if( m_iSelected < 0 )\r
4654         return NULL;\r
4655 \r
4656     DXUTComboBoxItem* pItem = m_Items.GetAt( m_iSelected );\r
4657     return pItem->pData;\r
4658 }\r
4659 \r
4660 \r
4661 //--------------------------------------------------------------------------------------\r
4662 DXUTComboBoxItem* CDXUTComboBox::GetSelectedItem()\r
4663 {\r
4664     if( m_iSelected < 0 )\r
4665         return NULL;\r
4666 \r
4667     return m_Items.GetAt( m_iSelected );\r
4668 }\r
4669 \r
4670 \r
4671 //--------------------------------------------------------------------------------------\r
4672 void* CDXUTComboBox::GetItemData( const WCHAR* strText )\r
4673 {\r
4674     int index = FindItem( strText );\r
4675     if( index == -1 )\r
4676     {\r
4677         return NULL;\r
4678     }\r
4679 \r
4680     DXUTComboBoxItem* pItem = m_Items.GetAt( index );\r
4681     if( pItem == NULL )\r
4682     {\r
4683         DXTRACE_ERR( L"CGrowableArray::GetAt", E_FAIL );\r
4684         return NULL;\r
4685     }\r
4686 \r
4687     return pItem->pData;\r
4688 }\r
4689 \r
4690 \r
4691 //--------------------------------------------------------------------------------------\r
4692 void* CDXUTComboBox::GetItemData( int nIndex )\r
4693 {\r
4694     if( nIndex < 0 || nIndex >= m_Items.GetSize() )\r
4695         return NULL;\r
4696 \r
4697     return m_Items.GetAt( nIndex )->pData;\r
4698 }\r
4699 \r
4700 \r
4701 //--------------------------------------------------------------------------------------\r
4702 HRESULT CDXUTComboBox::SetSelectedByIndex( UINT index )\r
4703 {\r
4704     if( index >= GetNumItems() )\r
4705         return E_INVALIDARG;\r
4706 \r
4707     m_iFocused = m_iSelected = index;\r
4708     m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, false, this );\r
4709 \r
4710     return S_OK;\r
4711 }\r
4712 \r
4713 \r
4714 \r
4715 //--------------------------------------------------------------------------------------\r
4716 HRESULT CDXUTComboBox::SetSelectedByText( const WCHAR* strText )\r
4717 {\r
4718     if( strText == NULL )\r
4719         return E_INVALIDARG;\r
4720 \r
4721     int index = FindItem( strText );\r
4722     if( index == -1 )\r
4723         return E_FAIL;\r
4724 \r
4725     m_iFocused = m_iSelected = index;\r
4726     m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, false, this );\r
4727 \r
4728     return S_OK;\r
4729 }\r
4730 \r
4731 \r
4732 \r
4733 //--------------------------------------------------------------------------------------\r
4734 HRESULT CDXUTComboBox::SetSelectedByData( void* pData )\r
4735 {\r
4736     for( int i = 0; i < m_Items.GetSize(); i++ )\r
4737     {\r
4738         DXUTComboBoxItem* pItem = m_Items.GetAt( i );\r
4739 \r
4740         if( pItem->pData == pData )\r
4741         {\r
4742             m_iFocused = m_iSelected = i;\r
4743             m_pDialog->SendEvent( EVENT_COMBOBOX_SELECTION_CHANGED, false, this );\r
4744             return S_OK;\r
4745         }\r
4746     }\r
4747 \r
4748     return E_FAIL;\r
4749 }\r
4750 \r
4751 \r
4752 \r
4753 //--------------------------------------------------------------------------------------\r
4754 CDXUTSlider::CDXUTSlider( CDXUTDialog* pDialog )\r
4755 {\r
4756     m_Type = DXUT_CONTROL_SLIDER;\r
4757     m_pDialog = pDialog;\r
4758 \r
4759     m_nMin = 0;\r
4760     m_nMax = 100;\r
4761     m_nValue = 50;\r
4762 \r
4763     m_bPressed = false;\r
4764 }\r
4765 \r
4766 \r
4767 //--------------------------------------------------------------------------------------\r
4768 BOOL CDXUTSlider::ContainsPoint( POINT pt )\r
4769 {\r
4770     return ( PtInRect( &m_rcBoundingBox, pt ) ||\r
4771              PtInRect( &m_rcButton, pt ) );\r
4772 }\r
4773 \r
4774 \r
4775 //--------------------------------------------------------------------------------------\r
4776 void CDXUTSlider::UpdateRects()\r
4777 {\r
4778     CDXUTControl::UpdateRects();\r
4779 \r
4780     m_rcButton = m_rcBoundingBox;\r
4781     m_rcButton.right = m_rcButton.left + RectHeight( m_rcButton );\r
4782     OffsetRect( &m_rcButton, -RectWidth( m_rcButton ) / 2, 0 );\r
4783 \r
4784     m_nButtonX = ( int )( ( m_nValue - m_nMin ) * ( float )RectWidth( m_rcBoundingBox ) / ( m_nMax - m_nMin ) );\r
4785     OffsetRect( &m_rcButton, m_nButtonX, 0 );\r
4786 }\r
4787 \r
4788 int CDXUTSlider::ValueFromPos( int x )\r
4789 {\r
4790     float fValuePerPixel = ( float )( m_nMax - m_nMin ) / RectWidth( m_rcBoundingBox );\r
4791     return ( int )( 0.5f + m_nMin + fValuePerPixel * ( x - m_rcBoundingBox.left ) );\r
4792 }\r
4793 \r
4794 //--------------------------------------------------------------------------------------\r
4795 bool CDXUTSlider::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
4796 {\r
4797     if( !m_bEnabled || !m_bVisible )\r
4798         return false;\r
4799 \r
4800     switch( uMsg )\r
4801     {\r
4802         case WM_KEYDOWN:\r
4803         {\r
4804             switch( wParam )\r
4805             {\r
4806                 case VK_HOME:\r
4807                     SetValueInternal( m_nMin, true );\r
4808                     return true;\r
4809 \r
4810                 case VK_END:\r
4811                     SetValueInternal( m_nMax, true );\r
4812                     return true;\r
4813 \r
4814                 case VK_LEFT:\r
4815                 case VK_DOWN:\r
4816                     SetValueInternal( m_nValue - 1, true );\r
4817                     return true;\r
4818 \r
4819                 case VK_RIGHT:\r
4820                 case VK_UP:\r
4821                     SetValueInternal( m_nValue + 1, true );\r
4822                     return true;\r
4823 \r
4824                 case VK_NEXT:\r
4825                     SetValueInternal( m_nValue - ( 10 > ( m_nMax - m_nMin ) / 10 ? 10 : ( m_nMax - m_nMin ) / 10 ),\r
4826                                       true );\r
4827                     return true;\r
4828 \r
4829                 case VK_PRIOR:\r
4830                     SetValueInternal( m_nValue + ( 10 > ( m_nMax - m_nMin ) / 10 ? 10 : ( m_nMax - m_nMin ) / 10 ),\r
4831                                       true );\r
4832                     return true;\r
4833             }\r
4834             break;\r
4835         }\r
4836     }\r
4837 \r
4838 \r
4839     return false;\r
4840 }\r
4841 \r
4842 \r
4843 //--------------------------------------------------------------------------------------\r
4844 bool CDXUTSlider::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam )\r
4845 {\r
4846     if( !m_bEnabled || !m_bVisible )\r
4847         return false;\r
4848 \r
4849     switch( uMsg )\r
4850     {\r
4851         case WM_LBUTTONDOWN:\r
4852         case WM_LBUTTONDBLCLK:\r
4853             {\r
4854                 if( PtInRect( &m_rcButton, pt ) )\r
4855                 {\r
4856                     // Pressed while inside the control\r
4857                     m_bPressed = true;\r
4858                     SetCapture( DXUTGetHWND() );\r
4859 \r
4860                     m_nDragX = pt.x;\r
4861                     //m_nDragY = pt.y;\r
4862                     m_nDragOffset = m_nButtonX - m_nDragX;\r
4863 \r
4864                     //m_nDragValue = m_nValue;\r
4865 \r
4866                     if( !m_bHasFocus )\r
4867                         m_pDialog->RequestFocus( this );\r
4868 \r
4869                     return true;\r
4870                 }\r
4871 \r
4872                 if( PtInRect( &m_rcBoundingBox, pt ) )\r
4873                 {\r
4874                     m_nDragX = pt.x;\r
4875                     m_nDragOffset = 0;\r
4876                     m_bPressed = true;\r
4877 \r
4878                     if( !m_bHasFocus )\r
4879                         m_pDialog->RequestFocus( this );\r
4880 \r
4881                     if( pt.x > m_nButtonX + m_x )\r
4882                     {\r
4883                         SetValueInternal( m_nValue + 1, true );\r
4884                         return true;\r
4885                     }\r
4886 \r
4887                     if( pt.x < m_nButtonX + m_x )\r
4888                     {\r
4889                         SetValueInternal( m_nValue - 1, true );\r
4890                         return true;\r
4891                     }\r
4892                 }\r
4893 \r
4894                 break;\r
4895             }\r
4896 \r
4897         case WM_LBUTTONUP:\r
4898         {\r
4899             if( m_bPressed )\r
4900             {\r
4901                 m_bPressed = false;\r
4902                 ReleaseCapture();\r
4903                 m_pDialog->SendEvent( EVENT_SLIDER_VALUE_CHANGED_UP, true, this );\r
4904 \r
4905                 return true;\r
4906             }\r
4907 \r
4908             break;\r
4909         }\r
4910 \r
4911         case WM_MOUSEMOVE:\r
4912         {\r
4913             if( m_bPressed )\r
4914             {\r
4915                 SetValueInternal( ValueFromPos( m_x + pt.x + m_nDragOffset ), true );\r
4916                 return true;\r
4917             }\r
4918 \r
4919             break;\r
4920         }\r
4921 \r
4922         case WM_MOUSEWHEEL:\r
4923         {\r
4924             int nScrollAmount = int( ( short )HIWORD( wParam ) ) / WHEEL_DELTA;\r
4925             SetValueInternal( m_nValue - nScrollAmount, true );\r
4926             return true;\r
4927         }\r
4928     };\r
4929 \r
4930     return false;\r
4931 }\r
4932 \r
4933 \r
4934 //--------------------------------------------------------------------------------------\r
4935 void CDXUTSlider::SetRange( int nMin, int nMax )\r
4936 {\r
4937     m_nMin = nMin;\r
4938     m_nMax = nMax;\r
4939 \r
4940     SetValueInternal( m_nValue, false );\r
4941 }\r
4942 \r
4943 \r
4944 //--------------------------------------------------------------------------------------\r
4945 void CDXUTSlider::SetValueInternal( int nValue, bool bFromInput )\r
4946 {\r
4947     // Clamp to range\r
4948     nValue = __max( m_nMin, nValue );\r
4949     nValue = __min( m_nMax, nValue );\r
4950 \r
4951     if( nValue == m_nValue )\r
4952         return;\r
4953 \r
4954     m_nValue = nValue;\r
4955     UpdateRects();\r
4956 \r
4957     m_pDialog->SendEvent( EVENT_SLIDER_VALUE_CHANGED, bFromInput, this );\r
4958 }\r
4959 \r
4960 \r
4961 //--------------------------------------------------------------------------------------\r
4962 void CDXUTSlider::Render( float fElapsedTime )\r
4963 {\r
4964     if( m_bVisible == false )\r
4965         return;\r
4966 \r
4967     int nOffsetX = 0;\r
4968     int nOffsetY = 0;\r
4969 \r
4970     DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL;\r
4971 \r
4972     if( m_bVisible == false )\r
4973     {\r
4974         iState = DXUT_STATE_HIDDEN;\r
4975     }\r
4976     else if( m_bEnabled == false )\r
4977     {\r
4978         iState = DXUT_STATE_DISABLED;\r
4979     }\r
4980     else if( m_bPressed )\r
4981     {\r
4982         iState = DXUT_STATE_PRESSED;\r
4983 \r
4984         nOffsetX = 1;\r
4985         nOffsetY = 2;\r
4986     }\r
4987     else if( m_bMouseOver )\r
4988     {\r
4989         iState = DXUT_STATE_MOUSEOVER;\r
4990 \r
4991         nOffsetX = -1;\r
4992         nOffsetY = -2;\r
4993     }\r
4994     else if( m_bHasFocus )\r
4995     {\r
4996         iState = DXUT_STATE_FOCUS;\r
4997     }\r
4998 \r
4999     float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f;\r
5000 \r
5001     CDXUTElement* pElement = m_Elements.GetAt( 0 );\r
5002 \r
5003     // Blend current color\r
5004     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
5005     m_pDialog->DrawSprite( pElement, &m_rcBoundingBox, DXUT_FAR_BUTTON_DEPTH );\r
5006 \r
5007     //TODO: remove magic numbers\r
5008     pElement = m_Elements.GetAt( 1 );\r
5009 \r
5010     // Blend current color\r
5011     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
5012     m_pDialog->DrawSprite( pElement, &m_rcButton, DXUT_NEAR_BUTTON_DEPTH );\r
5013 }\r
5014 \r
5015 \r
5016 //--------------------------------------------------------------------------------------\r
5017 // CDXUTScrollBar class\r
5018 //--------------------------------------------------------------------------------------\r
5019 \r
5020 //--------------------------------------------------------------------------------------\r
5021 CDXUTScrollBar::CDXUTScrollBar( CDXUTDialog* pDialog )\r
5022 {\r
5023     m_Type = DXUT_CONTROL_SCROLLBAR;\r
5024     m_pDialog = pDialog;\r
5025 \r
5026     m_bShowThumb = true;\r
5027     m_bDrag = false;\r
5028 \r
5029     SetRect( &m_rcUpButton, 0, 0, 0, 0 );\r
5030     SetRect( &m_rcDownButton, 0, 0, 0, 0 );\r
5031     SetRect( &m_rcTrack, 0, 0, 0, 0 );\r
5032     SetRect( &m_rcThumb, 0, 0, 0, 0 );\r
5033     m_nPosition = 0;\r
5034     m_nPageSize = 1;\r
5035     m_nStart = 0;\r
5036     m_nEnd = 1;\r
5037     m_Arrow = CLEAR;\r
5038     m_dArrowTS = 0.0;\r
5039 }\r
5040 \r
5041 \r
5042 //--------------------------------------------------------------------------------------\r
5043 CDXUTScrollBar::~CDXUTScrollBar()\r
5044 {\r
5045 }\r
5046 \r
5047 \r
5048 //--------------------------------------------------------------------------------------\r
5049 void CDXUTScrollBar::UpdateRects()\r
5050 {\r
5051     CDXUTControl::UpdateRects();\r
5052 \r
5053     // Make the buttons square\r
5054 \r
5055     SetRect( &m_rcUpButton, m_rcBoundingBox.left, m_rcBoundingBox.top,\r
5056              m_rcBoundingBox.right, m_rcBoundingBox.top + RectWidth( m_rcBoundingBox ) );\r
5057     SetRect( &m_rcDownButton, m_rcBoundingBox.left, m_rcBoundingBox.bottom - RectWidth( m_rcBoundingBox ),\r
5058              m_rcBoundingBox.right, m_rcBoundingBox.bottom );\r
5059     SetRect( &m_rcTrack, m_rcUpButton.left, m_rcUpButton.bottom,\r
5060              m_rcDownButton.right, m_rcDownButton.top );\r
5061     m_rcThumb.left = m_rcUpButton.left;\r
5062     m_rcThumb.right = m_rcUpButton.right;\r
5063 \r
5064     UpdateThumbRect();\r
5065 }\r
5066 \r
5067 \r
5068 //--------------------------------------------------------------------------------------\r
5069 // Compute the dimension of the scroll thumb\r
5070 void CDXUTScrollBar::UpdateThumbRect()\r
5071 {\r
5072     if( m_nEnd - m_nStart > m_nPageSize )\r
5073     {\r
5074         int nThumbHeight = __max( RectHeight( m_rcTrack ) * m_nPageSize / ( m_nEnd - m_nStart ),\r
5075                                   SCROLLBAR_MINTHUMBSIZE );\r
5076         int nMaxPosition = m_nEnd - m_nStart - m_nPageSize;\r
5077         m_rcThumb.top = m_rcTrack.top + ( m_nPosition - m_nStart ) * ( RectHeight( m_rcTrack ) - nThumbHeight )\r
5078             / nMaxPosition;\r
5079         m_rcThumb.bottom = m_rcThumb.top + nThumbHeight;\r
5080         m_bShowThumb = true;\r
5081 \r
5082     }\r
5083     else\r
5084     {\r
5085         // No content to scroll\r
5086         m_rcThumb.bottom = m_rcThumb.top;\r
5087         m_bShowThumb = false;\r
5088     }\r
5089 }\r
5090 \r
5091 \r
5092 //--------------------------------------------------------------------------------------\r
5093 // Scroll() scrolls by nDelta items.  A positive value scrolls down, while a negative\r
5094 // value scrolls up.\r
5095 void CDXUTScrollBar::Scroll( int nDelta )\r
5096 {\r
5097     // Perform scroll\r
5098     m_nPosition += nDelta;\r
5099 \r
5100     // Cap position\r
5101     Cap();\r
5102 \r
5103     // Update thumb position\r
5104     UpdateThumbRect();\r
5105 }\r
5106 \r
5107 \r
5108 //--------------------------------------------------------------------------------------\r
5109 void CDXUTScrollBar::ShowItem( int nIndex )\r
5110 {\r
5111     // Cap the index\r
5112 \r
5113     if( nIndex < 0 )\r
5114         nIndex = 0;\r
5115 \r
5116     if( nIndex >= m_nEnd )\r
5117         nIndex = m_nEnd - 1;\r
5118 \r
5119     // Adjust position\r
5120 \r
5121     if( m_nPosition > nIndex )\r
5122         m_nPosition = nIndex;\r
5123     else if( m_nPosition + m_nPageSize <= nIndex )\r
5124         m_nPosition = nIndex - m_nPageSize + 1;\r
5125 \r
5126     UpdateThumbRect();\r
5127 }\r
5128 \r
5129 \r
5130 //--------------------------------------------------------------------------------------\r
5131 bool CDXUTScrollBar::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
5132 {\r
5133     return false;\r
5134 }\r
5135 \r
5136 \r
5137 //--------------------------------------------------------------------------------------\r
5138 bool CDXUTScrollBar::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam )\r
5139 {\r
5140     static int ThumbOffsetY;\r
5141 \r
5142     m_LastMouse = pt;\r
5143     switch( uMsg )\r
5144     {\r
5145         case WM_LBUTTONDOWN:\r
5146         case WM_LBUTTONDBLCLK:\r
5147             {\r
5148                 // Check for click on up button\r
5149 \r
5150                 if( PtInRect( &m_rcUpButton, pt ) )\r
5151                 {\r
5152                     SetCapture( DXUTGetHWND() );\r
5153                     if( m_nPosition > m_nStart )\r
5154                         --m_nPosition;\r
5155                     UpdateThumbRect();\r
5156                     m_Arrow = CLICKED_UP;\r
5157                     m_dArrowTS = DXUTGetTime();\r
5158                     return true;\r
5159                 }\r
5160 \r
5161                 // Check for click on down button\r
5162 \r
5163                 if( PtInRect( &m_rcDownButton, pt ) )\r
5164                 {\r
5165                     SetCapture( DXUTGetHWND() );\r
5166                     if( m_nPosition + m_nPageSize < m_nEnd )\r
5167                         ++m_nPosition;\r
5168                     UpdateThumbRect();\r
5169                     m_Arrow = CLICKED_DOWN;\r
5170                     m_dArrowTS = DXUTGetTime();\r
5171                     return true;\r
5172                 }\r
5173 \r
5174                 // Check for click on thumb\r
5175 \r
5176                 if( PtInRect( &m_rcThumb, pt ) )\r
5177                 {\r
5178                     SetCapture( DXUTGetHWND() );\r
5179                     m_bDrag = true;\r
5180                     ThumbOffsetY = pt.y - m_rcThumb.top;\r
5181                     return true;\r
5182                 }\r
5183 \r
5184                 // Check for click on track\r
5185 \r
5186                 if( m_rcThumb.left <= pt.x &&\r
5187                     m_rcThumb.right > pt.x )\r
5188                 {\r
5189                     SetCapture( DXUTGetHWND() );\r
5190                     if( m_rcThumb.top > pt.y &&\r
5191                         m_rcTrack.top <= pt.y )\r
5192                     {\r
5193                         Scroll( -( m_nPageSize - 1 ) );\r
5194                         return true;\r
5195                     }\r
5196                     else if( m_rcThumb.bottom <= pt.y &&\r
5197                              m_rcTrack.bottom > pt.y )\r
5198                     {\r
5199                         Scroll( m_nPageSize - 1 );\r
5200                         return true;\r
5201                     }\r
5202                 }\r
5203 \r
5204                 break;\r
5205             }\r
5206 \r
5207         case WM_LBUTTONUP:\r
5208         {\r
5209             m_bDrag = false;\r
5210             ReleaseCapture();\r
5211             UpdateThumbRect();\r
5212             m_Arrow = CLEAR;\r
5213             break;\r
5214         }\r
5215 \r
5216         case WM_MOUSEMOVE:\r
5217         {\r
5218             if( m_bDrag )\r
5219             {\r
5220                 m_rcThumb.bottom += pt.y - ThumbOffsetY - m_rcThumb.top;\r
5221                 m_rcThumb.top = pt.y - ThumbOffsetY;\r
5222                 if( m_rcThumb.top < m_rcTrack.top )\r
5223                     OffsetRect( &m_rcThumb, 0, m_rcTrack.top - m_rcThumb.top );\r
5224                 else if( m_rcThumb.bottom > m_rcTrack.bottom )\r
5225                     OffsetRect( &m_rcThumb, 0, m_rcTrack.bottom - m_rcThumb.bottom );\r
5226 \r
5227                 // Compute first item index based on thumb position\r
5228 \r
5229                 int nMaxFirstItem = m_nEnd - m_nStart - m_nPageSize;  // Largest possible index for first item\r
5230                 int nMaxThumb = RectHeight( m_rcTrack ) - RectHeight( m_rcThumb );  // Largest possible thumb position from the top\r
5231 \r
5232                 m_nPosition = m_nStart +\r
5233                     ( m_rcThumb.top - m_rcTrack.top +\r
5234                       nMaxThumb / ( nMaxFirstItem * 2 ) ) * // Shift by half a row to avoid last row covered by only one pixel\r
5235                     nMaxFirstItem / nMaxThumb;\r
5236 \r
5237                 return true;\r
5238             }\r
5239 \r
5240             break;\r
5241         }\r
5242     }\r
5243 \r
5244     return false;\r
5245 }\r
5246 \r
5247 \r
5248 //--------------------------------------------------------------------------------------\r
5249 bool CDXUTScrollBar::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
5250 {\r
5251     if( WM_CAPTURECHANGED == uMsg )\r
5252     {\r
5253         // The application just lost mouse capture. We may not have gotten\r
5254         // the WM_MOUSEUP message, so reset m_bDrag here.\r
5255         if( ( HWND )lParam != DXUTGetHWND() )\r
5256             m_bDrag = false;\r
5257     }\r
5258 \r
5259     return false;\r
5260 }\r
5261 \r
5262 \r
5263 //--------------------------------------------------------------------------------------\r
5264 void CDXUTScrollBar::Render( float fElapsedTime )\r
5265 {\r
5266     if( m_bVisible == false )\r
5267         return;\r
5268 \r
5269     // Check if the arrow button has been held for a while.\r
5270     // If so, update the thumb position to simulate repeated\r
5271     // scroll.\r
5272     if( m_Arrow != CLEAR )\r
5273     {\r
5274         double dCurrTime = DXUTGetTime();\r
5275         if( PtInRect( &m_rcUpButton, m_LastMouse ) )\r
5276         {\r
5277             switch( m_Arrow )\r
5278             {\r
5279                 case CLICKED_UP:\r
5280                     if( SCROLLBAR_ARROWCLICK_DELAY < dCurrTime - m_dArrowTS )\r
5281                     {\r
5282                         Scroll( -1 );\r
5283                         m_Arrow = HELD_UP;\r
5284                         m_dArrowTS = dCurrTime;\r
5285                     }\r
5286                     break;\r
5287                 case HELD_UP:\r
5288                     if( SCROLLBAR_ARROWCLICK_REPEAT < dCurrTime - m_dArrowTS )\r
5289                     {\r
5290                         Scroll( -1 );\r
5291                         m_dArrowTS = dCurrTime;\r
5292                     }\r
5293                     break;\r
5294             }\r
5295         }\r
5296         else if( PtInRect( &m_rcDownButton, m_LastMouse ) )\r
5297         {\r
5298             switch( m_Arrow )\r
5299             {\r
5300                 case CLICKED_DOWN:\r
5301                     if( SCROLLBAR_ARROWCLICK_DELAY < dCurrTime - m_dArrowTS )\r
5302                     {\r
5303                         Scroll( 1 );\r
5304                         m_Arrow = HELD_DOWN;\r
5305                         m_dArrowTS = dCurrTime;\r
5306                     }\r
5307                     break;\r
5308                 case HELD_DOWN:\r
5309                     if( SCROLLBAR_ARROWCLICK_REPEAT < dCurrTime - m_dArrowTS )\r
5310                     {\r
5311                         Scroll( 1 );\r
5312                         m_dArrowTS = dCurrTime;\r
5313                     }\r
5314                     break;\r
5315             }\r
5316         }\r
5317     }\r
5318 \r
5319     DXUT_CONTROL_STATE iState = DXUT_STATE_NORMAL;\r
5320 \r
5321     if( m_bVisible == false )\r
5322         iState = DXUT_STATE_HIDDEN;\r
5323     else if( m_bEnabled == false || m_bShowThumb == false )\r
5324         iState = DXUT_STATE_DISABLED;\r
5325     else if( m_bMouseOver )\r
5326         iState = DXUT_STATE_MOUSEOVER;\r
5327     else if( m_bHasFocus )\r
5328         iState = DXUT_STATE_FOCUS;\r
5329 \r
5330 \r
5331     float fBlendRate = ( iState == DXUT_STATE_PRESSED ) ? 0.0f : 0.8f;\r
5332 \r
5333     // Background track layer\r
5334     CDXUTElement* pElement = m_Elements.GetAt( 0 );\r
5335 \r
5336     // Blend current color\r
5337     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
5338     m_pDialog->DrawSprite( pElement, &m_rcTrack, DXUT_FAR_BUTTON_DEPTH );\r
5339 \r
5340     // Up Arrow\r
5341     pElement = m_Elements.GetAt( 1 );\r
5342 \r
5343     // Blend current color\r
5344     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
5345     m_pDialog->DrawSprite( pElement, &m_rcUpButton, DXUT_NEAR_BUTTON_DEPTH );\r
5346 \r
5347     // Down Arrow\r
5348     pElement = m_Elements.GetAt( 2 );\r
5349 \r
5350     // Blend current color\r
5351     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
5352     m_pDialog->DrawSprite( pElement, &m_rcDownButton, DXUT_NEAR_BUTTON_DEPTH );\r
5353 \r
5354     // Thumb button\r
5355     pElement = m_Elements.GetAt( 3 );\r
5356 \r
5357     // Blend current color\r
5358     pElement->TextureColor.Blend( iState, fElapsedTime, fBlendRate );\r
5359     m_pDialog->DrawSprite( pElement, &m_rcThumb, DXUT_NEAR_BUTTON_DEPTH );\r
5360 \r
5361 }\r
5362 \r
5363 \r
5364 //--------------------------------------------------------------------------------------\r
5365 void CDXUTScrollBar::SetTrackRange( int nStart, int nEnd )\r
5366 {\r
5367     m_nStart = nStart; m_nEnd = nEnd;\r
5368     Cap();\r
5369     UpdateThumbRect();\r
5370 }\r
5371 \r
5372 \r
5373 //--------------------------------------------------------------------------------------\r
5374 void CDXUTScrollBar::Cap()  // Clips position at boundaries. Ensures it stays within legal range.\r
5375 {\r
5376     if( m_nPosition < m_nStart ||\r
5377         m_nEnd - m_nStart <= m_nPageSize )\r
5378     {\r
5379         m_nPosition = m_nStart;\r
5380     }\r
5381     else if( m_nPosition + m_nPageSize > m_nEnd )\r
5382         m_nPosition = m_nEnd - m_nPageSize;\r
5383 }\r
5384 \r
5385 //--------------------------------------------------------------------------------------\r
5386 // CDXUTListBox class\r
5387 //--------------------------------------------------------------------------------------\r
5388 \r
5389 //--------------------------------------------------------------------------------------\r
5390 CDXUTListBox::CDXUTListBox( CDXUTDialog* pDialog ) : m_ScrollBar( pDialog )\r
5391 {\r
5392     m_Type = DXUT_CONTROL_LISTBOX;\r
5393     m_pDialog = pDialog;\r
5394 \r
5395     m_dwStyle = 0;\r
5396     m_nSBWidth = 16;\r
5397     m_nSelected = -1;\r
5398     m_nSelStart = 0;\r
5399     m_bDrag = false;\r
5400     m_nBorder = 6;\r
5401     m_nMargin = 5;\r
5402     m_nTextHeight = 0;\r
5403 }\r
5404 \r
5405 \r
5406 //--------------------------------------------------------------------------------------\r
5407 CDXUTListBox::~CDXUTListBox()\r
5408 {\r
5409     RemoveAllItems();\r
5410 }\r
5411 \r
5412 \r
5413 //--------------------------------------------------------------------------------------\r
5414 void CDXUTListBox::UpdateRects()\r
5415 {\r
5416     CDXUTControl::UpdateRects();\r
5417 \r
5418     m_rcSelection = m_rcBoundingBox;\r
5419     m_rcSelection.right -= m_nSBWidth;\r
5420     InflateRect( &m_rcSelection, -m_nBorder, -m_nBorder );\r
5421     m_rcText = m_rcSelection;\r
5422     InflateRect( &m_rcText, -m_nMargin, 0 );\r
5423 \r
5424     // Update the scrollbar's rects\r
5425     m_ScrollBar.SetLocation( m_rcBoundingBox.right - m_nSBWidth, m_rcBoundingBox.top );\r
5426     m_ScrollBar.SetSize( m_nSBWidth, m_height );\r
5427     DXUTFontNode* pFontNode = m_pDialog->GetManager()->GetFontNode( m_Elements.GetAt( 0 )->iFont );\r
5428     if( pFontNode && pFontNode->nHeight )\r
5429     {\r
5430         m_ScrollBar.SetPageSize( RectHeight( m_rcText ) / pFontNode->nHeight );\r
5431 \r
5432         // The selected item may have been scrolled off the page.\r
5433         // Ensure that it is in page again.\r
5434         m_ScrollBar.ShowItem( m_nSelected );\r
5435     }\r
5436 }\r
5437 \r
5438 \r
5439 //--------------------------------------------------------------------------------------\r
5440 HRESULT CDXUTListBox::AddItem( const WCHAR* wszText, void* pData )\r
5441 {\r
5442     DXUTListBoxItem* pNewItem = new DXUTListBoxItem;\r
5443     if( !pNewItem )\r
5444         return E_OUTOFMEMORY;\r
5445 \r
5446     wcscpy_s( pNewItem->strText, 256, wszText );\r
5447     pNewItem->pData = pData;\r
5448     SetRect( &pNewItem->rcActive, 0, 0, 0, 0 );\r
5449     pNewItem->bSelected = false;\r
5450 \r
5451     HRESULT hr = m_Items.Add( pNewItem );\r
5452     if( FAILED( hr ) )\r
5453     {\r
5454         SAFE_DELETE( pNewItem );\r
5455     }\r
5456     else\r
5457     {\r
5458         m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() );\r
5459     }\r
5460 \r
5461     return hr;\r
5462 }\r
5463 \r
5464 \r
5465 //--------------------------------------------------------------------------------------\r
5466 HRESULT CDXUTListBox::InsertItem( int nIndex, const WCHAR* wszText, void* pData )\r
5467 {\r
5468     DXUTListBoxItem* pNewItem = new DXUTListBoxItem;\r
5469     if( !pNewItem )\r
5470         return E_OUTOFMEMORY;\r
5471 \r
5472     wcscpy_s( pNewItem->strText, 256, wszText );\r
5473     pNewItem->pData = pData;\r
5474     SetRect( &pNewItem->rcActive, 0, 0, 0, 0 );\r
5475     pNewItem->bSelected = false;\r
5476 \r
5477     HRESULT hr = m_Items.Insert( nIndex, pNewItem );\r
5478     if( SUCCEEDED( hr ) )\r
5479         m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() );\r
5480     else\r
5481         SAFE_DELETE( pNewItem );\r
5482 \r
5483     return hr;\r
5484 }\r
5485 \r
5486 \r
5487 //--------------------------------------------------------------------------------------\r
5488 void CDXUTListBox::RemoveItem( int nIndex )\r
5489 {\r
5490     if( nIndex < 0 || nIndex >= ( int )m_Items.GetSize() )\r
5491         return;\r
5492 \r
5493     DXUTListBoxItem* pItem = m_Items.GetAt( nIndex );\r
5494 \r
5495     delete pItem;\r
5496     m_Items.Remove( nIndex );\r
5497     m_ScrollBar.SetTrackRange( 0, m_Items.GetSize() );\r
5498     if( m_nSelected >= ( int )m_Items.GetSize() )\r
5499         m_nSelected = m_Items.GetSize() - 1;\r
5500 \r
5501     m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this );\r
5502 }\r
5503 \r
5504 \r
5505 \r
5506 \r
5507 \r
5508 //--------------------------------------------------------------------------------------\r
5509 void CDXUTListBox::RemoveAllItems()\r
5510 {\r
5511     for( int i = 0; i < m_Items.GetSize(); ++i )\r
5512     {\r
5513         DXUTListBoxItem* pItem = m_Items.GetAt( i );\r
5514         delete pItem;\r
5515     }\r
5516 \r
5517     m_Items.RemoveAll();\r
5518     m_ScrollBar.SetTrackRange( 0, 1 );\r
5519 }\r
5520 \r
5521 \r
5522 //--------------------------------------------------------------------------------------\r
5523 DXUTListBoxItem* CDXUTListBox::GetItem( int nIndex )\r
5524 {\r
5525     if( nIndex < 0 || nIndex >= ( int )m_Items.GetSize() )\r
5526         return NULL;\r
5527 \r
5528     return m_Items[nIndex];\r
5529 }\r
5530 \r
5531 \r
5532 //--------------------------------------------------------------------------------------\r
5533 // For single-selection listbox, returns the index of the selected item.\r
5534 // For multi-selection, returns the first selected item after the nPreviousSelected position.\r
5535 // To search for the first selected item, the app passes -1 for nPreviousSelected.  For\r
5536 // subsequent searches, the app passes the returned index back to GetSelectedIndex as.\r
5537 // nPreviousSelected.\r
5538 // Returns -1 on error or if no item is selected.\r
5539 int CDXUTListBox::GetSelectedIndex( int nPreviousSelected )\r
5540 {\r
5541     if( nPreviousSelected < -1 )\r
5542         return -1;\r
5543 \r
5544     if( m_dwStyle & MULTISELECTION )\r
5545     {\r
5546         // Multiple selection enabled. Search for the next item with the selected flag.\r
5547         for( int i = nPreviousSelected + 1; i < ( int )m_Items.GetSize(); ++i )\r
5548         {\r
5549             DXUTListBoxItem* pItem = m_Items.GetAt( i );\r
5550 \r
5551             if( pItem->bSelected )\r
5552                 return i;\r
5553         }\r
5554 \r
5555         return -1;\r
5556     }\r
5557     else\r
5558     {\r
5559         // Single selection\r
5560         return m_nSelected;\r
5561     }\r
5562 }\r
5563 \r
5564 \r
5565 //--------------------------------------------------------------------------------------\r
5566 void CDXUTListBox::SelectItem( int nNewIndex )\r
5567 {\r
5568     // If no item exists, do nothing.\r
5569     if( m_Items.GetSize() == 0 )\r
5570         return;\r
5571 \r
5572     int nOldSelected = m_nSelected;\r
5573 \r
5574     // Adjust m_nSelected\r
5575     m_nSelected = nNewIndex;\r
5576 \r
5577     // Perform capping\r
5578     if( m_nSelected < 0 )\r
5579         m_nSelected = 0;\r
5580     if( m_nSelected >= ( int )m_Items.GetSize() )\r
5581         m_nSelected = m_Items.GetSize() - 1;\r
5582 \r
5583     if( nOldSelected != m_nSelected )\r
5584     {\r
5585         if( m_dwStyle & MULTISELECTION )\r
5586         {\r
5587             m_Items[m_nSelected]->bSelected = true;\r
5588         }\r
5589 \r
5590         // Update selection start\r
5591         m_nSelStart = m_nSelected;\r
5592 \r
5593         // Adjust scroll bar\r
5594         m_ScrollBar.ShowItem( m_nSelected );\r
5595     }\r
5596 \r
5597     m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this );\r
5598 }\r
5599 \r
5600 \r
5601 //--------------------------------------------------------------------------------------\r
5602 bool CDXUTListBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
5603 {\r
5604     if( !m_bEnabled || !m_bVisible )\r
5605         return false;\r
5606 \r
5607     // Let the scroll bar have a chance to handle it first\r
5608     if( m_ScrollBar.HandleKeyboard( uMsg, wParam, lParam ) )\r
5609         return true;\r
5610 \r
5611     switch( uMsg )\r
5612     {\r
5613         case WM_KEYDOWN:\r
5614             switch( wParam )\r
5615             {\r
5616                 case VK_UP:\r
5617                 case VK_DOWN:\r
5618                 case VK_NEXT:\r
5619                 case VK_PRIOR:\r
5620                 case VK_HOME:\r
5621                 case VK_END:\r
5622                     {\r
5623                         // If no item exists, do nothing.\r
5624                         if( m_Items.GetSize() == 0 )\r
5625                             return true;\r
5626 \r
5627                         int nOldSelected = m_nSelected;\r
5628 \r
5629                         // Adjust m_nSelected\r
5630                         switch( wParam )\r
5631                         {\r
5632                             case VK_UP:\r
5633                                 --m_nSelected; break;\r
5634                             case VK_DOWN:\r
5635                                 ++m_nSelected; break;\r
5636                             case VK_NEXT:\r
5637                                 m_nSelected += m_ScrollBar.GetPageSize() - 1; break;\r
5638                             case VK_PRIOR:\r
5639                                 m_nSelected -= m_ScrollBar.GetPageSize() - 1; break;\r
5640                             case VK_HOME:\r
5641                                 m_nSelected = 0; break;\r
5642                             case VK_END:\r
5643                                 m_nSelected = m_Items.GetSize() - 1; break;\r
5644                         }\r
5645 \r
5646                         // Perform capping\r
5647                         if( m_nSelected < 0 )\r
5648                             m_nSelected = 0;\r
5649                         if( m_nSelected >= ( int )m_Items.GetSize() )\r
5650                             m_nSelected = m_Items.GetSize() - 1;\r
5651 \r
5652                         if( nOldSelected != m_nSelected )\r
5653                         {\r
5654                             if( m_dwStyle & MULTISELECTION )\r
5655                             {\r
5656                                 // Multiple selection\r
5657 \r
5658                                 // Clear all selection\r
5659                                 for( int i = 0; i < ( int )m_Items.GetSize(); ++i )\r
5660                                 {\r
5661                                     DXUTListBoxItem* pItem = m_Items[i];\r
5662                                     pItem->bSelected = false;\r
5663                                 }\r
5664 \r
5665                                 if( GetKeyState( VK_SHIFT ) < 0 )\r
5666                                 {\r
5667                                     // Select all items from m_nSelStart to\r
5668                                     // m_nSelected\r
5669                                     int nEnd = __max( m_nSelStart, m_nSelected );\r
5670 \r
5671                                     for( int n = __min( m_nSelStart, m_nSelected ); n <= nEnd; ++n )\r
5672                                         m_Items[n]->bSelected = true;\r
5673                                 }\r
5674                                 else\r
5675                                 {\r
5676                                     m_Items[m_nSelected]->bSelected = true;\r
5677 \r
5678                                     // Update selection start\r
5679                                     m_nSelStart = m_nSelected;\r
5680                                 }\r
5681                             }\r
5682                             else\r
5683                                 m_nSelStart = m_nSelected;\r
5684 \r
5685                             // Adjust scroll bar\r
5686 \r
5687                             m_ScrollBar.ShowItem( m_nSelected );\r
5688 \r
5689                             // Send notification\r
5690 \r
5691                             m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this );\r
5692                         }\r
5693                         return true;\r
5694                     }\r
5695 \r
5696                     // Space is the hotkey for double-clicking an item.\r
5697                     //\r
5698                 case VK_SPACE:\r
5699                     m_pDialog->SendEvent( EVENT_LISTBOX_ITEM_DBLCLK, true, this );\r
5700                     return true;\r
5701             }\r
5702             break;\r
5703     }\r
5704 \r
5705     return false;\r
5706 }\r
5707 \r
5708 \r
5709 //--------------------------------------------------------------------------------------\r
5710 bool CDXUTListBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam )\r
5711 {\r
5712     if( !m_bEnabled || !m_bVisible )\r
5713         return false;\r
5714 \r
5715     // First acquire focus\r
5716     if( WM_LBUTTONDOWN == uMsg )\r
5717         if( !m_bHasFocus )\r
5718             m_pDialog->RequestFocus( this );\r
5719 \r
5720     // Let the scroll bar handle it first.\r
5721     if( m_ScrollBar.HandleMouse( uMsg, pt, wParam, lParam ) )\r
5722         return true;\r
5723 \r
5724     switch( uMsg )\r
5725     {\r
5726         case WM_LBUTTONDOWN:\r
5727         case WM_LBUTTONDBLCLK:\r
5728             // Check for clicks in the text area\r
5729             if( m_Items.GetSize() > 0 && PtInRect( &m_rcSelection, pt ) )\r
5730             {\r
5731                 // Compute the index of the clicked item\r
5732 \r
5733                 int nClicked;\r
5734                 if( m_nTextHeight )\r
5735                     nClicked = m_ScrollBar.GetTrackPos() + ( pt.y - m_rcText.top ) / m_nTextHeight;\r
5736                 else\r
5737                     nClicked = -1;\r
5738 \r
5739                 // Only proceed if the click falls on top of an item.\r
5740 \r
5741                 if( nClicked >= m_ScrollBar.GetTrackPos() &&\r
5742                     nClicked < ( int )m_Items.GetSize() &&\r
5743                     nClicked < m_ScrollBar.GetTrackPos() + m_ScrollBar.GetPageSize() )\r
5744                 {\r
5745                     SetCapture( DXUTGetHWND() );\r
5746                     m_bDrag = true;\r
5747 \r
5748                     // If this is a double click, fire off an event and exit\r
5749                     // since the first click would have taken care of the selection\r
5750                     // updating.\r
5751                     if( uMsg == WM_LBUTTONDBLCLK )\r
5752                     {\r
5753                         m_pDialog->SendEvent( EVENT_LISTBOX_ITEM_DBLCLK, true, this );\r
5754                         return true;\r
5755                     }\r
5756 \r
5757                     m_nSelected = nClicked;\r
5758                     if( !( wParam & MK_SHIFT ) )\r
5759                         m_nSelStart = m_nSelected;\r
5760 \r
5761                     // If this is a multi-selection listbox, update per-item\r
5762                     // selection data.\r
5763 \r
5764                     if( m_dwStyle & MULTISELECTION )\r
5765                     {\r
5766                         // Determine behavior based on the state of Shift and Ctrl\r
5767 \r
5768                         DXUTListBoxItem* pSelItem = m_Items.GetAt( m_nSelected );\r
5769                         if( ( wParam & ( MK_SHIFT | MK_CONTROL ) ) == MK_CONTROL )\r
5770                         {\r
5771                             // Control click. Reverse the selection of this item.\r
5772 \r
5773                             pSelItem->bSelected = !pSelItem->bSelected;\r
5774                         }\r
5775                         else if( ( wParam & ( MK_SHIFT | MK_CONTROL ) ) == MK_SHIFT )\r
5776                         {\r
5777                             // Shift click. Set the selection for all items\r
5778                             // from last selected item to the current item.\r
5779                             // Clear everything else.\r
5780 \r
5781                             int nBegin = __min( m_nSelStart, m_nSelected );\r
5782                             int nEnd = __max( m_nSelStart, m_nSelected );\r
5783 \r
5784                             for( int i = 0; i < nBegin; ++i )\r
5785                             {\r
5786                                 DXUTListBoxItem* pItem = m_Items.GetAt( i );\r
5787                                 pItem->bSelected = false;\r
5788                             }\r
5789 \r
5790                             for( int i = nEnd + 1; i < ( int )m_Items.GetSize(); ++i )\r
5791                             {\r
5792                                 DXUTListBoxItem* pItem = m_Items.GetAt( i );\r
5793                                 pItem->bSelected = false;\r
5794                             }\r
5795 \r
5796                             for( int i = nBegin; i <= nEnd; ++i )\r
5797                             {\r
5798                                 DXUTListBoxItem* pItem = m_Items.GetAt( i );\r
5799                                 pItem->bSelected = true;\r
5800                             }\r
5801                         }\r
5802                         else if( ( wParam & ( MK_SHIFT | MK_CONTROL ) ) == ( MK_SHIFT | MK_CONTROL ) )\r
5803                         {\r
5804                             // Control-Shift-click.\r
5805 \r
5806                             // The behavior is:\r
5807                             //   Set all items from m_nSelStart to m_nSelected to\r
5808                             //     the same state as m_nSelStart, not including m_nSelected.\r
5809                             //   Set m_nSelected to selected.\r
5810 \r
5811                             int nBegin = __min( m_nSelStart, m_nSelected );\r
5812                             int nEnd = __max( m_nSelStart, m_nSelected );\r
5813 \r
5814                             // The two ends do not need to be set here.\r
5815 \r
5816                             bool bLastSelected = m_Items.GetAt( m_nSelStart )->bSelected;\r
5817                             for( int i = nBegin + 1; i < nEnd; ++i )\r
5818                             {\r
5819                                 DXUTListBoxItem* pItem = m_Items.GetAt( i );\r
5820                                 pItem->bSelected = bLastSelected;\r
5821                             }\r
5822 \r
5823                             pSelItem->bSelected = true;\r
5824 \r
5825                             // Restore m_nSelected to the previous value\r
5826                             // This matches the Windows behavior\r
5827 \r
5828                             m_nSelected = m_nSelStart;\r
5829                         }\r
5830                         else\r
5831                         {\r
5832                             // Simple click.  Clear all items and select the clicked\r
5833                             // item.\r
5834 \r
5835 \r
5836                             for( int i = 0; i < ( int )m_Items.GetSize(); ++i )\r
5837                             {\r
5838                                 DXUTListBoxItem* pItem = m_Items.GetAt( i );\r
5839                                 pItem->bSelected = false;\r
5840                             }\r
5841 \r
5842                             pSelItem->bSelected = true;\r
5843                         }\r
5844                     }  // End of multi-selection case\r
5845 \r
5846                     m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this );\r
5847                 }\r
5848 \r
5849                 return true;\r
5850             }\r
5851             break;\r
5852 \r
5853         case WM_LBUTTONUP:\r
5854         {\r
5855             ReleaseCapture();\r
5856             m_bDrag = false;\r
5857 \r
5858             if( m_nSelected != -1 )\r
5859             {\r
5860                 // Set all items between m_nSelStart and m_nSelected to\r
5861                 // the same state as m_nSelStart\r
5862                 int nEnd = __max( m_nSelStart, m_nSelected );\r
5863 \r
5864                 for( int n = __min( m_nSelStart, m_nSelected ) + 1; n < nEnd; ++n )\r
5865                     m_Items[n]->bSelected = m_Items[m_nSelStart]->bSelected;\r
5866                 m_Items[m_nSelected]->bSelected = m_Items[m_nSelStart]->bSelected;\r
5867 \r
5868                 // If m_nSelStart and m_nSelected are not the same,\r
5869                 // the user has dragged the mouse to make a selection.\r
5870                 // Notify the application of this.\r
5871                 if( m_nSelStart != m_nSelected )\r
5872                     m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this );\r
5873 \r
5874                 m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION_END, true, this );\r
5875             }\r
5876             return false;\r
5877         }\r
5878 \r
5879         case WM_MOUSEMOVE:\r
5880             if( m_bDrag )\r
5881             {\r
5882                 // Compute the index of the item below cursor\r
5883 \r
5884                 int nItem;\r
5885                 if( m_nTextHeight )\r
5886                     nItem = m_ScrollBar.GetTrackPos() + ( pt.y - m_rcText.top ) / m_nTextHeight;\r
5887                 else\r
5888                     nItem = -1;\r
5889 \r
5890                 // Only proceed if the cursor is on top of an item.\r
5891 \r
5892                 if( nItem >= ( int )m_ScrollBar.GetTrackPos() &&\r
5893                     nItem < ( int )m_Items.GetSize() &&\r
5894                     nItem < m_ScrollBar.GetTrackPos() + m_ScrollBar.GetPageSize() )\r
5895                 {\r
5896                     m_nSelected = nItem;\r
5897                     m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this );\r
5898                 }\r
5899                 else if( nItem < ( int )m_ScrollBar.GetTrackPos() )\r
5900                 {\r
5901                     // User drags the mouse above window top\r
5902                     m_ScrollBar.Scroll( -1 );\r
5903                     m_nSelected = m_ScrollBar.GetTrackPos();\r
5904                     m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this );\r
5905                 }\r
5906                 else if( nItem >= m_ScrollBar.GetTrackPos() + m_ScrollBar.GetPageSize() )\r
5907                 {\r
5908                     // User drags the mouse below window bottom\r
5909                     m_ScrollBar.Scroll( 1 );\r
5910                     m_nSelected = __min( ( int )m_Items.GetSize(), m_ScrollBar.GetTrackPos() +\r
5911                                          m_ScrollBar.GetPageSize() ) - 1;\r
5912                     m_pDialog->SendEvent( EVENT_LISTBOX_SELECTION, true, this );\r
5913                 }\r
5914             }\r
5915             break;\r
5916 \r
5917         case WM_MOUSEWHEEL:\r
5918         {\r
5919             UINT uLines;\r
5920             SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &uLines, 0 );\r
5921             int nScrollAmount = int( ( short )HIWORD( wParam ) ) / WHEEL_DELTA * uLines;\r
5922             m_ScrollBar.Scroll( -nScrollAmount );\r
5923             return true;\r
5924         }\r
5925     }\r
5926 \r
5927     return false;\r
5928 }\r
5929 \r
5930 \r
5931 //--------------------------------------------------------------------------------------\r
5932 bool CDXUTListBox::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
5933 {\r
5934     if( WM_CAPTURECHANGED == uMsg )\r
5935     {\r
5936         // The application just lost mouse capture. We may not have gotten\r
5937         // the WM_MOUSEUP message, so reset m_bDrag here.\r
5938         if( ( HWND )lParam != DXUTGetHWND() )\r
5939             m_bDrag = false;\r
5940     }\r
5941 \r
5942     return false;\r
5943 }\r
5944 \r
5945 \r
5946 //--------------------------------------------------------------------------------------\r
5947 void CDXUTListBox::Render( float fElapsedTime )\r
5948 {\r
5949     if( m_bVisible == false )\r
5950         return;\r
5951 \r
5952     CDXUTElement* pElement = m_Elements.GetAt( 0 );\r
5953     pElement->TextureColor.Blend( DXUT_STATE_NORMAL, fElapsedTime );\r
5954     pElement->FontColor.Blend( DXUT_STATE_NORMAL, fElapsedTime );\r
5955 \r
5956     CDXUTElement* pSelElement = m_Elements.GetAt( 1 );\r
5957     pSelElement->TextureColor.Blend( DXUT_STATE_NORMAL, fElapsedTime );\r
5958     pSelElement->FontColor.Blend( DXUT_STATE_NORMAL, fElapsedTime );\r
5959 \r
5960     m_pDialog->DrawSprite( pElement, &m_rcBoundingBox, DXUT_FAR_BUTTON_DEPTH );\r
5961 \r
5962     // Render the text\r
5963     if( m_Items.GetSize() > 0 )\r
5964     {\r
5965         // Find out the height of a single line of text\r
5966         RECT rc = m_rcText;\r
5967         RECT rcSel = m_rcSelection;\r
5968         rc.bottom = rc.top + m_pDialog->GetManager()->GetFontNode( pElement->iFont )->nHeight;\r
5969 \r
5970         // Update the line height formation\r
5971         m_nTextHeight = rc.bottom - rc.top;\r
5972 \r
5973         static bool bSBInit;\r
5974         if( !bSBInit )\r
5975         {\r
5976             // Update the page size of the scroll bar\r
5977             if( m_nTextHeight )\r
5978                 m_ScrollBar.SetPageSize( RectHeight( m_rcText ) / m_nTextHeight );\r
5979             else\r
5980                 m_ScrollBar.SetPageSize( RectHeight( m_rcText ) );\r
5981             bSBInit = true;\r
5982         }\r
5983 \r
5984         rc.right = m_rcText.right;\r
5985         for( int i = m_ScrollBar.GetTrackPos(); i < ( int )m_Items.GetSize(); ++i )\r
5986         {\r
5987             if( rc.bottom > m_rcText.bottom )\r
5988                 break;\r
5989 \r
5990             DXUTListBoxItem* pItem = m_Items.GetAt( i );\r
5991 \r
5992             // Determine if we need to render this item with the\r
5993             // selected element.\r
5994             bool bSelectedStyle = false;\r
5995 \r
5996             if( !( m_dwStyle & MULTISELECTION ) && i == m_nSelected )\r
5997                 bSelectedStyle = true;\r
5998             else if( m_dwStyle & MULTISELECTION )\r
5999             {\r
6000                 if( m_bDrag &&\r
6001                     ( ( i >= m_nSelected && i < m_nSelStart ) ||\r
6002                       ( i <= m_nSelected && i > m_nSelStart ) ) )\r
6003                     bSelectedStyle = m_Items[m_nSelStart]->bSelected;\r
6004                 else if( pItem->bSelected )\r
6005                     bSelectedStyle = true;\r
6006             }\r
6007 \r
6008             if( bSelectedStyle )\r
6009             {\r
6010                 rcSel.top = rc.top; rcSel.bottom = rc.bottom;\r
6011                 m_pDialog->DrawSprite( pSelElement, &rcSel, DXUT_NEAR_BUTTON_DEPTH );\r
6012                 m_pDialog->DrawText( pItem->strText, pSelElement, &rc );\r
6013             }\r
6014             else\r
6015                 m_pDialog->DrawText( pItem->strText, pElement, &rc );\r
6016 \r
6017             OffsetRect( &rc, 0, m_nTextHeight );\r
6018         }\r
6019     }\r
6020 \r
6021     // Render the scroll bar\r
6022 \r
6023     m_ScrollBar.Render( fElapsedTime );\r
6024 }\r
6025 \r
6026 \r
6027 // Static member initialization\r
6028 HINSTANCE               CUniBuffer::s_hDll = NULL;\r
6029 HRESULT ( WINAPI*CUniBuffer::_ScriptApplyDigitSubstitution )( const SCRIPT_DIGITSUBSTITUTE*, SCRIPT_CONTROL*,\r
6030                                                               SCRIPT_STATE* ) = Dummy_ScriptApplyDigitSubstitution;\r
6031 HRESULT ( WINAPI*CUniBuffer::_ScriptStringAnalyse )( HDC, const void*, int, int, int, DWORD, int, SCRIPT_CONTROL*,\r
6032                                                      SCRIPT_STATE*, const int*, SCRIPT_TABDEF*, const BYTE*,\r
6033                                                      SCRIPT_STRING_ANALYSIS* ) = Dummy_ScriptStringAnalyse;\r
6034 HRESULT ( WINAPI*CUniBuffer::_ScriptStringCPtoX )( SCRIPT_STRING_ANALYSIS, int, BOOL, int* ) = Dummy_ScriptStringCPtoX;\r
6035 HRESULT ( WINAPI*CUniBuffer::_ScriptStringXtoCP )( SCRIPT_STRING_ANALYSIS, int, int*, int* ) = Dummy_ScriptStringXtoCP;\r
6036 HRESULT ( WINAPI*CUniBuffer::_ScriptStringFree )( SCRIPT_STRING_ANALYSIS* ) = Dummy_ScriptStringFree;\r
6037 const SCRIPT_LOGATTR*   ( WINAPI*CUniBuffer::_ScriptString_pLogAttr )( SCRIPT_STRING_ANALYSIS ) =\r
6038     Dummy_ScriptString_pLogAttr;\r
6039 const int*              ( WINAPI*CUniBuffer::_ScriptString_pcOutChars )( SCRIPT_STRING_ANALYSIS ) =\r
6040     Dummy_ScriptString_pcOutChars;\r
6041 bool                    CDXUTEditBox::s_bHideCaret;   // If true, we don't render the caret.\r
6042 \r
6043 \r
6044 \r
6045 //--------------------------------------------------------------------------------------\r
6046 // CDXUTEditBox class\r
6047 //--------------------------------------------------------------------------------------\r
6048 \r
6049 // When scrolling, EDITBOX_SCROLLEXTENT is reciprocal of the amount to scroll.\r
6050 // If EDITBOX_SCROLLEXTENT = 4, then we scroll 1/4 of the control each time.\r
6051 #define EDITBOX_SCROLLEXTENT 4\r
6052 \r
6053 //--------------------------------------------------------------------------------------\r
6054 CDXUTEditBox::CDXUTEditBox( CDXUTDialog* pDialog )\r
6055 {\r
6056     m_Type = DXUT_CONTROL_EDITBOX;\r
6057     m_pDialog = pDialog;\r
6058 \r
6059     m_nBorder = 5;  // Default border width\r
6060     m_nSpacing = 4;  // Default spacing\r
6061 \r
6062     m_bCaretOn = true;\r
6063     m_dfBlink = GetCaretBlinkTime() * 0.001f;\r
6064     m_dfLastBlink = DXUTGetGlobalTimer()->GetAbsoluteTime();\r
6065     s_bHideCaret = false;\r
6066     m_nFirstVisible = 0;\r
6067     m_TextColor = D3DCOLOR_ARGB( 255, 16, 16, 16 );\r
6068     m_SelTextColor = D3DCOLOR_ARGB( 255, 255, 255, 255 );\r
6069     m_SelBkColor = D3DCOLOR_ARGB( 255, 40, 50, 92 );\r
6070     m_CaretColor = D3DCOLOR_ARGB( 255, 0, 0, 0 );\r
6071     m_nCaret = m_nSelStart = 0;\r
6072     m_bInsertMode = true;\r
6073 \r
6074     m_bMouseDrag = false;\r
6075 }\r
6076 \r
6077 \r
6078 //--------------------------------------------------------------------------------------\r
6079 CDXUTEditBox::~CDXUTEditBox()\r
6080 {\r
6081 }\r
6082 \r
6083 \r
6084 //--------------------------------------------------------------------------------------\r
6085 // PlaceCaret: Set the caret to a character position, and adjust the scrolling if\r
6086 //             necessary.\r
6087 //--------------------------------------------------------------------------------------\r
6088 void CDXUTEditBox::PlaceCaret( int nCP )\r
6089 {\r
6090     assert( nCP >= 0 && nCP <= m_Buffer.GetTextSize() );\r
6091     m_nCaret = nCP;\r
6092 \r
6093     // Obtain the X offset of the character.\r
6094     int nX1st, nX, nX2;\r
6095     m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nX1st );  // 1st visible char\r
6096     m_Buffer.CPtoX( nCP, FALSE, &nX );  // LEAD\r
6097     // If nCP is the NULL terminator, get the leading edge instead of trailing.\r
6098     if( nCP == m_Buffer.GetTextSize() )\r
6099         nX2 = nX;\r
6100     else\r
6101         m_Buffer.CPtoX( nCP, TRUE, &nX2 );  // TRAIL\r
6102 \r
6103     // If the left edge of the char is smaller than the left edge of the 1st visible char,\r
6104     // we need to scroll left until this char is visible.\r
6105     if( nX < nX1st )\r
6106     {\r
6107         // Simply make the first visible character the char at the new caret position.\r
6108         m_nFirstVisible = nCP;\r
6109     }\r
6110     else // If the right of the character is bigger than the offset of the control's\r
6111     // right edge, we need to scroll right to this character.\r
6112     if( nX2 > nX1st + RectWidth( m_rcText ) )\r
6113     {\r
6114         // Compute the X of the new left-most pixel\r
6115         int nXNewLeft = nX2 - RectWidth( m_rcText );\r
6116 \r
6117         // Compute the char position of this character\r
6118         int nCPNew1st, nNewTrail;\r
6119         m_Buffer.XtoCP( nXNewLeft, &nCPNew1st, &nNewTrail );\r
6120 \r
6121         // If this coordinate is not on a character border,\r
6122         // start from the next character so that the caret\r
6123         // position does not fall outside the text rectangle.\r
6124         int nXNew1st;\r
6125         m_Buffer.CPtoX( nCPNew1st, FALSE, &nXNew1st );\r
6126         if( nXNew1st < nXNewLeft )\r
6127             ++nCPNew1st;\r
6128 \r
6129         m_nFirstVisible = nCPNew1st;\r
6130     }\r
6131 }\r
6132 \r
6133 \r
6134 //--------------------------------------------------------------------------------------\r
6135 void CDXUTEditBox::ClearText()\r
6136 {\r
6137     m_Buffer.Clear();\r
6138     m_nFirstVisible = 0;\r
6139     PlaceCaret( 0 );\r
6140     m_nSelStart = 0;\r
6141 }\r
6142 \r
6143 \r
6144 //--------------------------------------------------------------------------------------\r
6145 void CDXUTEditBox::SetText( LPCWSTR wszText, bool bSelected )\r
6146 {\r
6147     assert( wszText != NULL );\r
6148 \r
6149     m_Buffer.SetText( wszText );\r
6150     m_nFirstVisible = 0;\r
6151     // Move the caret to the end of the text\r
6152     PlaceCaret( m_Buffer.GetTextSize() );\r
6153     m_nSelStart = bSelected ? 0 : m_nCaret;\r
6154 }\r
6155 \r
6156 \r
6157 //--------------------------------------------------------------------------------------\r
6158 HRESULT CDXUTEditBox::GetTextCopy( __out_ecount(bufferCount) LPWSTR strDest, \r
6159                                    UINT bufferCount  )\r
6160 {\r
6161     assert( strDest );\r
6162 \r
6163     wcscpy_s( strDest, bufferCount, m_Buffer.GetBuffer() );\r
6164 \r
6165     return S_OK;\r
6166 }\r
6167 \r
6168 \r
6169 //--------------------------------------------------------------------------------------\r
6170 void CDXUTEditBox::DeleteSelectionText()\r
6171 {\r
6172     int nFirst = __min( m_nCaret, m_nSelStart );\r
6173     int nLast = __max( m_nCaret, m_nSelStart );\r
6174     // Update caret and selection\r
6175     PlaceCaret( nFirst );\r
6176     m_nSelStart = m_nCaret;\r
6177     // Remove the characters\r
6178     for( int i = nFirst; i < nLast; ++i )\r
6179         m_Buffer.RemoveChar( nFirst );\r
6180 }\r
6181 \r
6182 \r
6183 //--------------------------------------------------------------------------------------\r
6184 void CDXUTEditBox::UpdateRects()\r
6185 {\r
6186     CDXUTControl::UpdateRects();\r
6187 \r
6188     // Update the text rectangle\r
6189     m_rcText = m_rcBoundingBox;\r
6190     // First inflate by m_nBorder to compute render rects\r
6191     InflateRect( &m_rcText, -m_nBorder, -m_nBorder );\r
6192 \r
6193     // Update the render rectangles\r
6194     m_rcRender[0] = m_rcText;\r
6195     SetRect( &m_rcRender[1], m_rcBoundingBox.left, m_rcBoundingBox.top, m_rcText.left, m_rcText.top );\r
6196     SetRect( &m_rcRender[2], m_rcText.left, m_rcBoundingBox.top, m_rcText.right, m_rcText.top );\r
6197     SetRect( &m_rcRender[3], m_rcText.right, m_rcBoundingBox.top, m_rcBoundingBox.right, m_rcText.top );\r
6198     SetRect( &m_rcRender[4], m_rcBoundingBox.left, m_rcText.top, m_rcText.left, m_rcText.bottom );\r
6199     SetRect( &m_rcRender[5], m_rcText.right, m_rcText.top, m_rcBoundingBox.right, m_rcText.bottom );\r
6200     SetRect( &m_rcRender[6], m_rcBoundingBox.left, m_rcText.bottom, m_rcText.left, m_rcBoundingBox.bottom );\r
6201     SetRect( &m_rcRender[7], m_rcText.left, m_rcText.bottom, m_rcText.right, m_rcBoundingBox.bottom );\r
6202     SetRect( &m_rcRender[8], m_rcText.right, m_rcText.bottom, m_rcBoundingBox.right, m_rcBoundingBox.bottom );\r
6203 \r
6204     // Inflate further by m_nSpacing\r
6205     InflateRect( &m_rcText, -m_nSpacing, -m_nSpacing );\r
6206 }\r
6207 \r
6208 \r
6209 void CDXUTEditBox::CopyToClipboard()\r
6210 {\r
6211     // Copy the selection text to the clipboard\r
6212     if( m_nCaret != m_nSelStart && OpenClipboard( NULL ) )\r
6213     {\r
6214         EmptyClipboard();\r
6215 \r
6216         HGLOBAL hBlock = GlobalAlloc( GMEM_MOVEABLE, sizeof( WCHAR ) * ( m_Buffer.GetTextSize() + 1 ) );\r
6217         if( hBlock )\r
6218         {\r
6219             WCHAR* pwszText = ( WCHAR* )GlobalLock( hBlock );\r
6220             if( pwszText )\r
6221             {\r
6222                 int nFirst = __min( m_nCaret, m_nSelStart );\r
6223                 int nLast = __max( m_nCaret, m_nSelStart );\r
6224                 if( nLast - nFirst > 0 )\r
6225                     CopyMemory( pwszText, m_Buffer.GetBuffer() + nFirst, ( nLast - nFirst ) * sizeof( WCHAR ) );\r
6226                 pwszText[nLast - nFirst] = L'\0';  // Terminate it\r
6227                 GlobalUnlock( hBlock );\r
6228             }\r
6229             SetClipboardData( CF_UNICODETEXT, hBlock );\r
6230         }\r
6231         CloseClipboard();\r
6232         // We must not free the object until CloseClipboard is called.\r
6233         if( hBlock )\r
6234             GlobalFree( hBlock );\r
6235     }\r
6236 }\r
6237 \r
6238 \r
6239 void CDXUTEditBox::PasteFromClipboard()\r
6240 {\r
6241     DeleteSelectionText();\r
6242 \r
6243     if( OpenClipboard( NULL ) )\r
6244     {\r
6245         HANDLE handle = GetClipboardData( CF_UNICODETEXT );\r
6246         if( handle )\r
6247         {\r
6248             // Convert the ANSI string to Unicode, then\r
6249             // insert to our buffer.\r
6250             WCHAR* pwszText = ( WCHAR* )GlobalLock( handle );\r
6251             if( pwszText )\r
6252             {\r
6253                 // Copy all characters up to null.\r
6254                 if( m_Buffer.InsertString( m_nCaret, pwszText ) )\r
6255                     PlaceCaret( m_nCaret + lstrlenW( pwszText ) );\r
6256                 m_nSelStart = m_nCaret;\r
6257                 GlobalUnlock( handle );\r
6258             }\r
6259         }\r
6260         CloseClipboard();\r
6261     }\r
6262 }\r
6263 \r
6264 \r
6265 //--------------------------------------------------------------------------------------\r
6266 bool CDXUTEditBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
6267 {\r
6268     if( !m_bEnabled || !m_bVisible )\r
6269         return false;\r
6270 \r
6271     bool bHandled = false;\r
6272 \r
6273     switch( uMsg )\r
6274     {\r
6275         case WM_KEYDOWN:\r
6276         {\r
6277             switch( wParam )\r
6278             {\r
6279                 case VK_TAB:\r
6280                     // We don't process Tab in case keyboard input is enabled and the user\r
6281                     // wishes to Tab to other controls.\r
6282                     break;\r
6283 \r
6284                 case VK_HOME:\r
6285                     PlaceCaret( 0 );\r
6286                     if( GetKeyState( VK_SHIFT ) >= 0 )\r
6287                         // Shift is not down. Update selection\r
6288                         // start along with the caret.\r
6289                         m_nSelStart = m_nCaret;\r
6290                     ResetCaretBlink();\r
6291                     bHandled = true;\r
6292                     break;\r
6293 \r
6294                 case VK_END:\r
6295                     PlaceCaret( m_Buffer.GetTextSize() );\r
6296                     if( GetKeyState( VK_SHIFT ) >= 0 )\r
6297                         // Shift is not down. Update selection\r
6298                         // start along with the caret.\r
6299                         m_nSelStart = m_nCaret;\r
6300                     ResetCaretBlink();\r
6301                     bHandled = true;\r
6302                     break;\r
6303 \r
6304                 case VK_INSERT:\r
6305                     if( GetKeyState( VK_CONTROL ) < 0 )\r
6306                     {\r
6307                         // Control Insert. Copy to clipboard\r
6308                         CopyToClipboard();\r
6309                     }\r
6310                     else if( GetKeyState( VK_SHIFT ) < 0 )\r
6311                     {\r
6312                         // Shift Insert. Paste from clipboard\r
6313                         PasteFromClipboard();\r
6314                     }\r
6315                     else\r
6316                     {\r
6317                         // Toggle caret insert mode\r
6318                         m_bInsertMode = !m_bInsertMode;\r
6319                     }\r
6320                     break;\r
6321 \r
6322                 case VK_DELETE:\r
6323                     // Check if there is a text selection.\r
6324                     if( m_nCaret != m_nSelStart )\r
6325                     {\r
6326                         DeleteSelectionText();\r
6327                         m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this );\r
6328                     }\r
6329                     else\r
6330                     {\r
6331                         // Deleting one character\r
6332                         if( m_Buffer.RemoveChar( m_nCaret ) )\r
6333                             m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this );\r
6334                     }\r
6335                     ResetCaretBlink();\r
6336                     bHandled = true;\r
6337                     break;\r
6338 \r
6339                 case VK_LEFT:\r
6340                     if( GetKeyState( VK_CONTROL ) < 0 )\r
6341                     {\r
6342                         // Control is down. Move the caret to a new item\r
6343                         // instead of a character.\r
6344                         m_Buffer.GetPriorItemPos( m_nCaret, &m_nCaret );\r
6345                         PlaceCaret( m_nCaret );\r
6346                     }\r
6347                     else if( m_nCaret > 0 )\r
6348                         PlaceCaret( m_nCaret - 1 );\r
6349                     if( GetKeyState( VK_SHIFT ) >= 0 )\r
6350                         // Shift is not down. Update selection\r
6351                         // start along with the caret.\r
6352                         m_nSelStart = m_nCaret;\r
6353                     ResetCaretBlink();\r
6354                     bHandled = true;\r
6355                     break;\r
6356 \r
6357                 case VK_RIGHT:\r
6358                     if( GetKeyState( VK_CONTROL ) < 0 )\r
6359                     {\r
6360                         // Control is down. Move the caret to a new item\r
6361                         // instead of a character.\r
6362                         m_Buffer.GetNextItemPos( m_nCaret, &m_nCaret );\r
6363                         PlaceCaret( m_nCaret );\r
6364                     }\r
6365                     else if( m_nCaret < m_Buffer.GetTextSize() )\r
6366                         PlaceCaret( m_nCaret + 1 );\r
6367                     if( GetKeyState( VK_SHIFT ) >= 0 )\r
6368                         // Shift is not down. Update selection\r
6369                         // start along with the caret.\r
6370                         m_nSelStart = m_nCaret;\r
6371                     ResetCaretBlink();\r
6372                     bHandled = true;\r
6373                     break;\r
6374 \r
6375                 case VK_UP:\r
6376                 case VK_DOWN:\r
6377                     // Trap up and down arrows so that the dialog\r
6378                     // does not switch focus to another control.\r
6379                     bHandled = true;\r
6380                     break;\r
6381 \r
6382                 default:\r
6383                     bHandled = wParam != VK_ESCAPE;  // Let the application handle Esc.\r
6384             }\r
6385         }\r
6386     }\r
6387     return bHandled;\r
6388 }\r
6389 \r
6390 \r
6391 //--------------------------------------------------------------------------------------\r
6392 bool CDXUTEditBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam )\r
6393 {\r
6394     if( !m_bEnabled || !m_bVisible )\r
6395         return false;\r
6396 \r
6397     switch( uMsg )\r
6398     {\r
6399         case WM_LBUTTONDOWN:\r
6400         case WM_LBUTTONDBLCLK:\r
6401             {\r
6402                 if( !m_bHasFocus )\r
6403                     m_pDialog->RequestFocus( this );\r
6404 \r
6405                 if( !ContainsPoint( pt ) )\r
6406                     return false;\r
6407 \r
6408                 m_bMouseDrag = true;\r
6409                 SetCapture( DXUTGetHWND() );\r
6410                 // Determine the character corresponding to the coordinates.\r
6411                 int nCP, nTrail, nX1st;\r
6412                 m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nX1st );  // X offset of the 1st visible char\r
6413                 if( SUCCEEDED( m_Buffer.XtoCP( pt.x - m_rcText.left + nX1st, &nCP, &nTrail ) ) )\r
6414                 {\r
6415                     // Cap at the NULL character.\r
6416                     if( nTrail && nCP < m_Buffer.GetTextSize() )\r
6417                         PlaceCaret( nCP + 1 );\r
6418                     else\r
6419                         PlaceCaret( nCP );\r
6420                     m_nSelStart = m_nCaret;\r
6421                     ResetCaretBlink();\r
6422                 }\r
6423                 return true;\r
6424             }\r
6425 \r
6426         case WM_LBUTTONUP:\r
6427             ReleaseCapture();\r
6428             m_bMouseDrag = false;\r
6429             break;\r
6430 \r
6431         case WM_MOUSEMOVE:\r
6432             if( m_bMouseDrag )\r
6433             {\r
6434                 // Determine the character corresponding to the coordinates.\r
6435                 int nCP, nTrail, nX1st;\r
6436                 m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nX1st );  // X offset of the 1st visible char\r
6437                 if( SUCCEEDED( m_Buffer.XtoCP( pt.x - m_rcText.left + nX1st, &nCP, &nTrail ) ) )\r
6438                 {\r
6439                     // Cap at the NULL character.\r
6440                     if( nTrail && nCP < m_Buffer.GetTextSize() )\r
6441                         PlaceCaret( nCP + 1 );\r
6442                     else\r
6443                         PlaceCaret( nCP );\r
6444                 }\r
6445             }\r
6446             break;\r
6447     }\r
6448 \r
6449     return false;\r
6450 }\r
6451 \r
6452 \r
6453 //--------------------------------------------------------------------------------------\r
6454 void CDXUTEditBox::OnFocusIn()\r
6455 {\r
6456     CDXUTControl::OnFocusIn();\r
6457 \r
6458     ResetCaretBlink();\r
6459 }\r
6460 \r
6461 \r
6462 //--------------------------------------------------------------------------------------\r
6463 bool CDXUTEditBox::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam )\r
6464 {\r
6465     if( !m_bEnabled || !m_bVisible )\r
6466         return false;\r
6467 \r
6468     switch( uMsg )\r
6469     {\r
6470             // Make sure that while editing, the keyup and keydown messages associated with \r
6471             // WM_CHAR messages don't go to any non-focused controls or cameras\r
6472         case WM_KEYUP:\r
6473         case WM_KEYDOWN:\r
6474             return true;\r
6475 \r
6476         case WM_CHAR:\r
6477         {\r
6478             switch( ( WCHAR )wParam )\r
6479             {\r
6480                     // Backspace\r
6481                 case VK_BACK:\r
6482                 {\r
6483                     // If there's a selection, treat this\r
6484                     // like a delete key.\r
6485                     if( m_nCaret != m_nSelStart )\r
6486                     {\r
6487                         DeleteSelectionText();\r
6488                         m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this );\r
6489                     }\r
6490                     else if( m_nCaret > 0 )\r
6491                     {\r
6492                         // Move the caret, then delete the char.\r
6493                         PlaceCaret( m_nCaret - 1 );\r
6494                         m_nSelStart = m_nCaret;\r
6495                         m_Buffer.RemoveChar( m_nCaret );\r
6496                         m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this );\r
6497                     }\r
6498                     ResetCaretBlink();\r
6499                     break;\r
6500                 }\r
6501 \r
6502                 case 24:        // Ctrl-X Cut\r
6503                 case VK_CANCEL: // Ctrl-C Copy\r
6504                     {\r
6505                         CopyToClipboard();\r
6506 \r
6507                         // If the key is Ctrl-X, delete the selection too.\r
6508                         if( ( WCHAR )wParam == 24 )\r
6509                         {\r
6510                             DeleteSelectionText();\r
6511                             m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this );\r
6512                         }\r
6513 \r
6514                         break;\r
6515                     }\r
6516 \r
6517                     // Ctrl-V Paste\r
6518                 case 22:\r
6519                 {\r
6520                     PasteFromClipboard();\r
6521                     m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this );\r
6522                     break;\r
6523                 }\r
6524 \r
6525                     // Ctrl-A Select All\r
6526                 case 1:\r
6527                     if( m_nSelStart == m_nCaret )\r
6528                     {\r
6529                         m_nSelStart = 0;\r
6530                         PlaceCaret( m_Buffer.GetTextSize() );\r
6531                     }\r
6532                     break;\r
6533 \r
6534                 case VK_RETURN:\r
6535                     // Invoke the callback when the user presses Enter.\r
6536                     m_pDialog->SendEvent( EVENT_EDITBOX_STRING, true, this );\r
6537                     break;\r
6538 \r
6539                     // Junk characters we don't want in the string\r
6540                 case 26:  // Ctrl Z\r
6541                 case 2:   // Ctrl B\r
6542                 case 14:  // Ctrl N\r
6543                 case 19:  // Ctrl S\r
6544                 case 4:   // Ctrl D\r
6545                 case 6:   // Ctrl F\r
6546                 case 7:   // Ctrl G\r
6547                 case 10:  // Ctrl J\r
6548                 case 11:  // Ctrl K\r
6549                 case 12:  // Ctrl L\r
6550                 case 17:  // Ctrl Q\r
6551                 case 23:  // Ctrl W\r
6552                 case 5:   // Ctrl E\r
6553                 case 18:  // Ctrl R\r
6554                 case 20:  // Ctrl T\r
6555                 case 25:  // Ctrl Y\r
6556                 case 21:  // Ctrl U\r
6557                 case 9:   // Ctrl I\r
6558                 case 15:  // Ctrl O\r
6559                 case 16:  // Ctrl P\r
6560                 case 27:  // Ctrl [\r
6561                 case 29:  // Ctrl ]\r
6562                 case 28:  // Ctrl \ \r
6563                     break;\r
6564 \r
6565                 default:\r
6566                 {\r
6567                     // If there's a selection and the user\r
6568                     // starts to type, the selection should\r
6569                     // be deleted.\r
6570                     if( m_nCaret != m_nSelStart )\r
6571                         DeleteSelectionText();\r
6572 \r
6573                     // If we are in overwrite mode and there is already\r
6574                     // a char at the caret's position, simply replace it.\r
6575                     // Otherwise, we insert the char as normal.\r
6576                     if( !m_bInsertMode && m_nCaret < m_Buffer.GetTextSize() )\r
6577                     {\r
6578                         m_Buffer[m_nCaret] = ( WCHAR )wParam;\r
6579                         PlaceCaret( m_nCaret + 1 );\r
6580                         m_nSelStart = m_nCaret;\r
6581                     }\r
6582                     else\r
6583                     {\r
6584                         // Insert the char\r
6585                         if( m_Buffer.InsertChar( m_nCaret, ( WCHAR )wParam ) )\r
6586                         {\r
6587                             PlaceCaret( m_nCaret + 1 );\r
6588                             m_nSelStart = m_nCaret;\r
6589                         }\r
6590                     }\r
6591                     ResetCaretBlink();\r
6592                     m_pDialog->SendEvent( EVENT_EDITBOX_CHANGE, true, this );\r
6593                 }\r
6594             }\r
6595             return true;\r
6596         }\r
6597     }\r
6598     return false;\r
6599 }\r
6600 \r
6601 \r
6602 //--------------------------------------------------------------------------------------\r
6603 void CDXUTEditBox::Render( float fElapsedTime )\r
6604 {\r
6605     if( m_bVisible == false )\r
6606         return;\r
6607 \r
6608     HRESULT hr;\r
6609     int nSelStartX = 0, nCaretX = 0;  // Left and right X cordinates of the selection region\r
6610 \r
6611     CDXUTElement* pElement = GetElement( 0 );\r
6612     if( pElement )\r
6613     {\r
6614         m_Buffer.SetFontNode( m_pDialog->GetFont( pElement->iFont ) );\r
6615         PlaceCaret( m_nCaret );  // Call PlaceCaret now that we have the font info (node),\r
6616         // so that scrolling can be handled.\r
6617     }\r
6618 \r
6619     // Render the control graphics\r
6620     for( int e = 0; e < 9; ++e )\r
6621     {\r
6622         pElement = m_Elements.GetAt( e );\r
6623         pElement->TextureColor.Blend( DXUT_STATE_NORMAL, fElapsedTime );\r
6624 \r
6625         m_pDialog->DrawSprite( pElement, &m_rcRender[e], DXUT_FAR_BUTTON_DEPTH );\r
6626     }\r
6627 \r
6628     //\r
6629     // Compute the X coordinates of the first visible character.\r
6630     //\r
6631     int nXFirst;\r
6632     m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nXFirst );\r
6633 \r
6634     //\r
6635     // Compute the X coordinates of the selection rectangle\r
6636     //\r
6637     hr = m_Buffer.CPtoX( m_nCaret, FALSE, &nCaretX );\r
6638     if( m_nCaret != m_nSelStart )\r
6639         hr = m_Buffer.CPtoX( m_nSelStart, FALSE, &nSelStartX );\r
6640     else\r
6641         nSelStartX = nCaretX;\r
6642 \r
6643     //\r
6644     // Render the selection rectangle\r
6645     //\r
6646     RECT rcSelection;  // Make this available for rendering selected text\r
6647     if( m_nCaret != m_nSelStart )\r
6648     {\r
6649         int nSelLeftX = nCaretX, nSelRightX = nSelStartX;\r
6650         // Swap if left is bigger than right\r
6651         if( nSelLeftX > nSelRightX )\r
6652         {\r
6653             int nTemp = nSelLeftX; nSelLeftX = nSelRightX; nSelRightX = nTemp;\r
6654         }\r
6655 \r
6656         SetRect( &rcSelection, nSelLeftX, m_rcText.top, nSelRightX, m_rcText.bottom );\r
6657         OffsetRect( &rcSelection, m_rcText.left - nXFirst, 0 );\r
6658         IntersectRect( &rcSelection, &m_rcText, &rcSelection );\r
6659 \r
6660         IDirect3DDevice9* pd3dDevice = m_pDialog->GetManager()->GetD3D9Device();\r
6661         if( pd3dDevice )\r
6662             pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );\r
6663         m_pDialog->DrawRect( &rcSelection, m_SelBkColor );\r
6664         if( pd3dDevice )\r
6665             pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );\r
6666     }\r
6667 \r
6668     //\r
6669     // Render the text\r
6670     //\r
6671     // Element 0 for text\r
6672     m_Elements.GetAt( 0 )->FontColor.Current = m_TextColor;\r
6673     m_pDialog->DrawText( m_Buffer.GetBuffer() + m_nFirstVisible, m_Elements.GetAt( 0 ), &m_rcText );\r
6674 \r
6675     // Render the selected text\r
6676     if( m_nCaret != m_nSelStart )\r
6677     {\r
6678         int nFirstToRender = __max( m_nFirstVisible, __min( m_nSelStart, m_nCaret ) );\r
6679         int nNumChatToRender = __max( m_nSelStart, m_nCaret ) - nFirstToRender;\r
6680         m_Elements.GetAt( 0 )->FontColor.Current = m_SelTextColor;\r
6681         m_pDialog->DrawText( m_Buffer.GetBuffer() + nFirstToRender,\r
6682                              m_Elements.GetAt( 0 ), &rcSelection, false, nNumChatToRender );\r
6683     }\r
6684 \r
6685     //\r
6686     // Blink the caret\r
6687     //\r
6688     if( DXUTGetGlobalTimer()->GetAbsoluteTime() - m_dfLastBlink >= m_dfBlink )\r
6689     {\r
6690         m_bCaretOn = !m_bCaretOn;\r
6691         m_dfLastBlink = DXUTGetGlobalTimer()->GetAbsoluteTime();\r
6692     }\r
6693 \r
6694     //\r
6695     // Render the caret if this control has the focus\r
6696     //\r
6697     if( m_bHasFocus && m_bCaretOn && !s_bHideCaret )\r
6698     {\r
6699         // Start the rectangle with insert mode caret\r
6700         RECT rcCaret =\r
6701         {\r
6702             m_rcText.left - nXFirst + nCaretX - 1, m_rcText.top,\r
6703             m_rcText.left - nXFirst + nCaretX + 1, m_rcText.bottom\r
6704         };\r
6705 \r
6706         // If we are in overwrite mode, adjust the caret rectangle\r
6707         // to fill the entire character.\r
6708         if( !m_bInsertMode )\r
6709         {\r
6710             // Obtain the right edge X coord of the current character\r
6711             int nRightEdgeX;\r
6712             m_Buffer.CPtoX( m_nCaret, TRUE, &nRightEdgeX );\r
6713             rcCaret.right = m_rcText.left - nXFirst + nRightEdgeX;\r
6714         }\r
6715 \r
6716         m_pDialog->DrawRect( &rcCaret, m_CaretColor );\r
6717     }\r
6718 }\r
6719 \r
6720 \r
6721 #define IN_FLOAT_CHARSET( c ) \\r
6722     ( (c) == L'-' || (c) == L'.' || ( (c) >= L'0' && (c) <= L'9' ) )\r
6723 \r
6724 void CDXUTEditBox::ParseFloatArray( float* pNumbers, int nCount )\r
6725 {\r
6726     int nWritten = 0;  // Number of floats written\r
6727     const WCHAR* pToken, *pEnd;\r
6728     WCHAR wszToken[60];\r
6729 \r
6730     pToken = m_Buffer.GetBuffer();\r
6731     while( nWritten < nCount && *pToken != L'\0' )\r
6732     {\r
6733         // Skip leading spaces\r
6734         while( *pToken == L' ' )\r
6735             ++pToken;\r
6736 \r
6737         if( *pToken == L'\0' )\r
6738             break;\r
6739 \r
6740         // Locate the end of number\r
6741         pEnd = pToken;\r
6742         while( IN_FLOAT_CHARSET( *pEnd ) )\r
6743             ++pEnd;\r
6744 \r
6745         // Copy the token to our buffer\r
6746         int nTokenLen = __min( sizeof( wszToken ) / sizeof( wszToken[0] ) - 1, int( pEnd - pToken ) );\r
6747         wcscpy_s( wszToken, nTokenLen, pToken );\r
6748         *pNumbers = ( float )wcstod( wszToken, NULL );\r
6749         ++nWritten;\r
6750         ++pNumbers;\r
6751         pToken = pEnd;\r
6752     }\r
6753 }\r
6754 \r
6755 \r
6756 void CDXUTEditBox::SetTextFloatArray( const float* pNumbers, int nCount )\r
6757 {\r
6758     WCHAR wszBuffer[512] =\r
6759     {\r
6760         0\r
6761     };\r
6762     WCHAR wszTmp[64];\r
6763 \r
6764     if( pNumbers == NULL )\r
6765         return;\r
6766 \r
6767     for( int i = 0; i < nCount; ++i )\r
6768     {\r
6769         swprintf_s( wszTmp, 64, L"%.4f ", pNumbers[i] );\r
6770         wcscat_s( wszBuffer, 512, wszTmp );\r
6771     }\r
6772 \r
6773     // Don't want the last space\r
6774     if( nCount > 0 && wcslen( wszBuffer ) > 0 )\r
6775         wszBuffer[wcslen( wszBuffer ) - 1] = 0;\r
6776 \r
6777     SetText( wszBuffer );\r
6778 }\r
6779 \r
6780 \r
6781 \r
6782 \r
6783 //--------------------------------------------------------------------------------------\r
6784 void CUniBuffer::Initialize()\r
6785 {\r
6786     if( s_hDll ) // Only need to do once\r
6787         return;\r
6788 \r
6789     s_hDll = LoadLibrary( UNISCRIBE_DLLNAME );\r
6790     if( s_hDll )\r
6791     {\r
6792         FARPROC Temp;\r
6793         GETPROCADDRESS( s_hDll, ScriptApplyDigitSubstitution, Temp );\r
6794         GETPROCADDRESS( s_hDll, ScriptStringAnalyse, Temp );\r
6795         GETPROCADDRESS( s_hDll, ScriptStringCPtoX, Temp );\r
6796         GETPROCADDRESS( s_hDll, ScriptStringXtoCP, Temp );\r
6797         GETPROCADDRESS( s_hDll, ScriptStringFree, Temp );\r
6798         GETPROCADDRESS( s_hDll, ScriptString_pLogAttr, Temp );\r
6799         GETPROCADDRESS( s_hDll, ScriptString_pcOutChars, Temp );\r
6800     }\r
6801 }\r
6802 \r
6803 \r
6804 //--------------------------------------------------------------------------------------\r
6805 void CUniBuffer::Uninitialize()\r
6806 {\r
6807     if( s_hDll )\r
6808     {\r
6809         PLACEHOLDERPROC( ScriptApplyDigitSubstitution );\r
6810         PLACEHOLDERPROC( ScriptStringAnalyse );\r
6811         PLACEHOLDERPROC( ScriptStringCPtoX );\r
6812         PLACEHOLDERPROC( ScriptStringXtoCP );\r
6813         PLACEHOLDERPROC( ScriptStringFree );\r
6814         PLACEHOLDERPROC( ScriptString_pLogAttr );\r
6815         PLACEHOLDERPROC( ScriptString_pcOutChars );\r
6816 \r
6817         FreeLibrary( s_hDll );\r
6818         s_hDll = NULL;\r
6819     }\r
6820 }\r
6821 \r
6822 \r
6823 //--------------------------------------------------------------------------------------\r
6824 bool CUniBuffer::SetBufferSize( int nNewSize )\r
6825 {\r
6826     // If the current size is already the maximum allowed,\r
6827     // we can't possibly allocate more.\r
6828     if( m_nBufferSize == DXUT_MAX_EDITBOXLENGTH )\r
6829         return false;\r
6830 \r
6831     int nAllocateSize = ( nNewSize == -1 || nNewSize < m_nBufferSize * 2 ) ? ( m_nBufferSize ? m_nBufferSize *\r
6832                                                                                2 : 256 ) : nNewSize * 2;\r
6833 \r
6834     // Cap the buffer size at the maximum allowed.\r
6835     if( nAllocateSize > DXUT_MAX_EDITBOXLENGTH )\r
6836         nAllocateSize = DXUT_MAX_EDITBOXLENGTH;\r
6837 \r
6838     WCHAR* pTempBuffer = new WCHAR[nAllocateSize];\r
6839     if( !pTempBuffer )\r
6840         return false;\r
6841 \r
6842     ZeroMemory( pTempBuffer, sizeof( WCHAR ) * nAllocateSize );\r
6843 \r
6844     if( m_pwszBuffer )\r
6845     {\r
6846         CopyMemory( pTempBuffer, m_pwszBuffer, m_nBufferSize * sizeof( WCHAR ) );\r
6847         delete[] m_pwszBuffer;\r
6848     }\r
6849 \r
6850     m_pwszBuffer = pTempBuffer;\r
6851     m_nBufferSize = nAllocateSize;\r
6852     return true;\r
6853 }\r
6854 \r
6855 \r
6856 //--------------------------------------------------------------------------------------\r
6857 // Uniscribe -- Analyse() analyses the string in the buffer\r
6858 //--------------------------------------------------------------------------------------\r
6859 HRESULT CUniBuffer::Analyse()\r
6860 {\r
6861     if( m_Analysis )\r
6862         _ScriptStringFree( &m_Analysis );\r
6863 \r
6864     SCRIPT_CONTROL ScriptControl; // For uniscribe\r
6865     SCRIPT_STATE ScriptState;   // For uniscribe\r
6866     ZeroMemory( &ScriptControl, sizeof( ScriptControl ) );\r
6867     ZeroMemory( &ScriptState, sizeof( ScriptState ) );\r
6868     _ScriptApplyDigitSubstitution( NULL, &ScriptControl, &ScriptState );\r
6869 \r
6870     if( !m_pFontNode )\r
6871         return E_FAIL;\r
6872 \r
6873     HDC hDC = \r
6874         ( m_pFontNode->pFont9 ? m_pFontNode->pFont9->GetDC() : NULL );\r
6875     HRESULT hr = _ScriptStringAnalyse( hDC,\r
6876                                        m_pwszBuffer,\r
6877                                        lstrlenW( m_pwszBuffer ) + 1,  // NULL is also analyzed.\r
6878                                        lstrlenW( m_pwszBuffer ) * 3 / 2 + 16,\r
6879                                        -1,\r
6880                                        SSA_BREAK | SSA_GLYPHS | SSA_FALLBACK | SSA_LINK,\r
6881                                        0,\r
6882                                        &ScriptControl,\r
6883                                        &ScriptState,\r
6884                                        NULL,\r
6885                                        NULL,\r
6886                                        NULL,\r
6887                                        &m_Analysis );\r
6888     if( SUCCEEDED( hr ) )\r
6889         m_bAnalyseRequired = false;  // Analysis is up-to-date\r
6890     return hr;\r
6891 }\r
6892 \r
6893 \r
6894 //--------------------------------------------------------------------------------------\r
6895 CUniBuffer::CUniBuffer( int nInitialSize )\r
6896 {\r
6897     CUniBuffer::Initialize();  // ensure static vars are properly init'ed first\r
6898 \r
6899     m_nBufferSize = 0;\r
6900     m_pwszBuffer = NULL;\r
6901     m_bAnalyseRequired = true;\r
6902     m_Analysis = NULL;\r
6903     m_pFontNode = NULL;\r
6904 \r
6905     if( nInitialSize > 0 )\r
6906         SetBufferSize( nInitialSize );\r
6907 }\r
6908 \r
6909 \r
6910 //--------------------------------------------------------------------------------------\r
6911 CUniBuffer::~CUniBuffer()\r
6912 {\r
6913     delete[] m_pwszBuffer;\r
6914     if( m_Analysis )\r
6915         _ScriptStringFree( &m_Analysis );\r
6916 }\r
6917 \r
6918 \r
6919 //--------------------------------------------------------------------------------------\r
6920 WCHAR& CUniBuffer::operator[]( int n )  // No param checking\r
6921 {\r
6922     // This version of operator[] is called only\r
6923     // if we are asking for write access, so\r
6924     // re-analysis is required.\r
6925     m_bAnalyseRequired = true;\r
6926     return m_pwszBuffer[n];\r
6927 }\r
6928 \r
6929 \r
6930 //--------------------------------------------------------------------------------------\r
6931 void CUniBuffer::Clear()\r
6932 {\r
6933     *m_pwszBuffer = L'\0';\r
6934     m_bAnalyseRequired = true;\r
6935 }\r
6936 \r
6937 \r
6938 //--------------------------------------------------------------------------------------\r
6939 // Inserts the char at specified index.\r
6940 // If nIndex == -1, insert to the end.\r
6941 //--------------------------------------------------------------------------------------\r
6942 bool CUniBuffer::InsertChar( int nIndex, WCHAR wChar )\r
6943 {\r
6944     assert( nIndex >= 0 );\r
6945 \r
6946     if( nIndex < 0 || nIndex > lstrlenW( m_pwszBuffer ) )\r
6947         return false;  // invalid index\r
6948 \r
6949     // Check for maximum length allowed\r
6950     if( GetTextSize() + 1 >= DXUT_MAX_EDITBOXLENGTH )\r
6951         return false;\r
6952 \r
6953     if( lstrlenW( m_pwszBuffer ) + 1 >= m_nBufferSize )\r
6954     {\r
6955         if( !SetBufferSize( -1 ) )\r
6956             return false;  // out of memory\r
6957     }\r
6958 \r
6959     assert( m_nBufferSize >= 2 );\r
6960 \r
6961     // Shift the characters after the index, start by copying the null terminator\r
6962     WCHAR* dest = m_pwszBuffer + lstrlenW( m_pwszBuffer ) + 1;\r
6963     WCHAR* stop = m_pwszBuffer + nIndex;\r
6964     WCHAR* src = dest - 1;\r
6965 \r
6966     while( dest > stop )\r
6967     {\r
6968         *dest-- = *src--;\r
6969     }\r
6970 \r
6971     // Set new character\r
6972     m_pwszBuffer[ nIndex ] = wChar;\r
6973     m_bAnalyseRequired = true;\r
6974 \r
6975     return true;\r
6976 }\r
6977 \r
6978 \r
6979 //--------------------------------------------------------------------------------------\r
6980 // Removes the char at specified index.\r
6981 // If nIndex == -1, remove the last char.\r
6982 //--------------------------------------------------------------------------------------\r
6983 bool CUniBuffer::RemoveChar( int nIndex )\r
6984 {\r
6985     if( !lstrlenW( m_pwszBuffer ) || nIndex < 0 || nIndex >= lstrlenW( m_pwszBuffer ) )\r
6986         return false;  // Invalid index\r
6987 \r
6988     MoveMemory( m_pwszBuffer + nIndex, m_pwszBuffer + nIndex + 1, sizeof( WCHAR ) *\r
6989                 ( lstrlenW( m_pwszBuffer ) - nIndex ) );\r
6990     m_bAnalyseRequired = true;\r
6991     return true;\r
6992 }\r
6993 \r
6994 \r
6995 //--------------------------------------------------------------------------------------\r
6996 // Inserts the first nCount characters of the string pStr at specified index.\r
6997 // If nCount == -1, the entire string is inserted.\r
6998 // If nIndex == -1, insert to the end.\r
6999 //--------------------------------------------------------------------------------------\r
7000 bool CUniBuffer::InsertString( int nIndex, const WCHAR* pStr, int nCount )\r
7001 {\r
7002     assert( nIndex >= 0 );\r
7003     if( nIndex < 0 )\r
7004         return false;\r
7005 \r
7006     if( nIndex > lstrlenW( m_pwszBuffer ) )\r
7007         return false;  // invalid index\r
7008 \r
7009     if( -1 == nCount )\r
7010         nCount = lstrlenW( pStr );\r
7011 \r
7012     // Check for maximum length allowed\r
7013     if( GetTextSize() + nCount >= DXUT_MAX_EDITBOXLENGTH )\r
7014         return false;\r
7015 \r
7016     if( lstrlenW( m_pwszBuffer ) + nCount >= m_nBufferSize )\r
7017     {\r
7018         if( !SetBufferSize( lstrlenW( m_pwszBuffer ) + nCount + 1 ) )\r
7019             return false;  // out of memory\r
7020     }\r
7021 \r
7022     MoveMemory( m_pwszBuffer + nIndex + nCount, m_pwszBuffer + nIndex, sizeof( WCHAR ) *\r
7023                 ( lstrlenW( m_pwszBuffer ) - nIndex + 1 ) );\r
7024     CopyMemory( m_pwszBuffer + nIndex, pStr, nCount * sizeof( WCHAR ) );\r
7025     m_bAnalyseRequired = true;\r
7026 \r
7027     return true;\r
7028 }\r
7029 \r
7030 \r
7031 //--------------------------------------------------------------------------------------\r
7032 bool CUniBuffer::SetText( LPCWSTR wszText )\r
7033 {\r
7034     assert( wszText != NULL );\r
7035 \r
7036     int nRequired = int( wcslen( wszText ) + 1 );\r
7037 \r
7038     // Check for maximum length allowed\r
7039     if( nRequired >= DXUT_MAX_EDITBOXLENGTH )\r
7040         return false;\r
7041 \r
7042     while( GetBufferSize() < nRequired )\r
7043         if( !SetBufferSize( -1 ) )\r
7044             break;\r
7045     // Check again in case out of memory occurred inside while loop.\r
7046     if( GetBufferSize() >= nRequired )\r
7047     {\r
7048         wcscpy_s( m_pwszBuffer, GetBufferSize(), wszText );\r
7049         m_bAnalyseRequired = true;\r
7050         return true;\r
7051     }\r
7052     else\r
7053         return false;\r
7054 }\r
7055 \r
7056 \r
7057 //--------------------------------------------------------------------------------------\r
7058 HRESULT CUniBuffer::CPtoX( int nCP, BOOL bTrail, int* pX )\r
7059 {\r
7060     assert( pX );\r
7061     *pX = 0;  // Default\r
7062 \r
7063     HRESULT hr = S_OK;\r
7064     if( m_bAnalyseRequired )\r
7065         hr = Analyse();\r
7066 \r
7067     if( SUCCEEDED( hr ) )\r
7068         hr = _ScriptStringCPtoX( m_Analysis, nCP, bTrail, pX );\r
7069 \r
7070     return hr;\r
7071 }\r
7072 \r
7073 \r
7074 //--------------------------------------------------------------------------------------\r
7075 HRESULT CUniBuffer::XtoCP( int nX, int* pCP, int* pnTrail )\r
7076 {\r
7077     assert( pCP && pnTrail );\r
7078     *pCP = 0; *pnTrail = FALSE;  // Default\r
7079 \r
7080     HRESULT hr = S_OK;\r
7081     if( m_bAnalyseRequired )\r
7082         hr = Analyse();\r
7083 \r
7084     if( SUCCEEDED( hr ) )\r
7085         hr = _ScriptStringXtoCP( m_Analysis, nX, pCP, pnTrail );\r
7086 \r
7087     // If the coordinate falls outside the text region, we\r
7088     // can get character positions that don't exist.  We must\r
7089     // filter them here and convert them to those that do exist.\r
7090     if( *pCP == -1 && *pnTrail == TRUE )\r
7091     {\r
7092         *pCP = 0; *pnTrail = FALSE;\r
7093     }\r
7094     else if( *pCP > lstrlenW( m_pwszBuffer ) && *pnTrail == FALSE )\r
7095     {\r
7096         *pCP = lstrlenW( m_pwszBuffer ); *pnTrail = TRUE;\r
7097     }\r
7098 \r
7099     return hr;\r
7100 }\r
7101 \r
7102 \r
7103 //--------------------------------------------------------------------------------------\r
7104 void CUniBuffer::GetPriorItemPos( int nCP, int* pPrior )\r
7105 {\r
7106     *pPrior = nCP;  // Default is the char itself\r
7107 \r
7108     if( m_bAnalyseRequired )\r
7109         if( FAILED( Analyse() ) )\r
7110             return;\r
7111 \r
7112     const SCRIPT_LOGATTR* pLogAttr = _ScriptString_pLogAttr( m_Analysis );\r
7113     if( !pLogAttr )\r
7114         return;\r
7115 \r
7116     if( !_ScriptString_pcOutChars( m_Analysis ) )\r
7117         return;\r
7118     int nInitial = *_ScriptString_pcOutChars( m_Analysis );\r
7119     if( nCP - 1 < nInitial )\r
7120         nInitial = nCP - 1;\r
7121     for( int i = nInitial; i > 0; --i )\r
7122         if( pLogAttr[i].fWordStop ||       // Either the fWordStop flag is set\r
7123             ( !pLogAttr[i].fWhiteSpace &&  // Or the previous char is whitespace but this isn't.\r
7124               pLogAttr[i - 1].fWhiteSpace ) )\r
7125         {\r
7126             *pPrior = i;\r
7127             return;\r
7128         }\r
7129     // We have reached index 0.  0 is always a break point, so simply return it.\r
7130     *pPrior = 0;\r
7131 }\r
7132 \r
7133 \r
7134 //--------------------------------------------------------------------------------------\r
7135 void CUniBuffer::GetNextItemPos( int nCP, int* pPrior )\r
7136 {\r
7137     *pPrior = nCP;  // Default is the char itself\r
7138 \r
7139     HRESULT hr = S_OK;\r
7140     if( m_bAnalyseRequired )\r
7141         hr = Analyse();\r
7142     if( FAILED( hr ) )\r
7143         return;\r
7144 \r
7145     const SCRIPT_LOGATTR* pLogAttr = _ScriptString_pLogAttr( m_Analysis );\r
7146     if( !pLogAttr )\r
7147         return;\r
7148 \r
7149     if( !_ScriptString_pcOutChars( m_Analysis ) )\r
7150         return;\r
7151     int nInitial = *_ScriptString_pcOutChars( m_Analysis );\r
7152     if( nCP + 1 < nInitial )\r
7153         nInitial = nCP + 1;\r
7154 \r
7155     int i = nInitial;\r
7156     int limit = *_ScriptString_pcOutChars( m_Analysis );\r
7157     while( limit > 0 && i < limit - 1 )\r
7158     {\r
7159         if( pLogAttr[i].fWordStop )      // Either the fWordStop flag is set\r
7160         {\r
7161             *pPrior = i;\r
7162             return;\r
7163         }\r
7164         else if( pLogAttr[i].fWhiteSpace &&  // Or this whitespace but the next char isn't.\r
7165                  !pLogAttr[i + 1].fWhiteSpace )\r
7166         {\r
7167             *pPrior = i + 1;  // The next char is a word stop\r
7168             return;\r
7169         }\r
7170 \r
7171         ++i;\r
7172         limit = *_ScriptString_pcOutChars( m_Analysis );\r
7173     }\r
7174     // We have reached the end. It's always a word stop, so simply return it.\r
7175     *pPrior = *_ScriptString_pcOutChars( m_Analysis ) - 1;\r
7176 }\r
7177 \r
7178 \r
7179 //--------------------------------------------------------------------------------------\r
7180 void CDXUTEditBox::ResetCaretBlink()\r
7181 {\r
7182     m_bCaretOn = true;\r
7183     m_dfLastBlink = DXUTGetGlobalTimer()->GetAbsoluteTime();\r
7184 }\r
7185 \r
7186 \r
7187 //--------------------------------------------------------------------------------------\r
7188 void DXUTBlendColor::Init( D3DCOLOR defaultColor, D3DCOLOR disabledColor, D3DCOLOR hiddenColor )\r
7189 {\r
7190     for( int i = 0; i < MAX_CONTROL_STATES; i++ )\r
7191     {\r
7192         States[ i ] = defaultColor;\r
7193     }\r
7194 \r
7195     States[ DXUT_STATE_DISABLED ] = disabledColor;\r
7196     States[ DXUT_STATE_HIDDEN ] = hiddenColor;\r
7197     Current = hiddenColor;\r
7198 }\r
7199 \r
7200 \r
7201 //--------------------------------------------------------------------------------------\r
7202 void DXUTBlendColor::Blend( UINT iState, float fElapsedTime, float fRate )\r
7203 {\r
7204     D3DXCOLOR destColor = States[ iState ];\r
7205     D3DXColorLerp( &Current, &Current, &destColor, 1.0f - powf( fRate, 30 * fElapsedTime ) );\r
7206 }\r
7207 \r
7208 \r
7209 \r
7210 //--------------------------------------------------------------------------------------\r
7211 void CDXUTElement::SetTexture( UINT iTexture, RECT* prcTexture, D3DCOLOR defaultTextureColor )\r
7212 {\r
7213     this->iTexture = iTexture;\r
7214 \r
7215     if( prcTexture )\r
7216         rcTexture = *prcTexture;\r
7217     else\r
7218         SetRectEmpty( &rcTexture );\r
7219 \r
7220     TextureColor.Init( defaultTextureColor );\r
7221 }\r
7222 \r
7223 \r
7224 //--------------------------------------------------------------------------------------\r
7225 void CDXUTElement::SetFont( UINT iFont, D3DCOLOR defaultFontColor, DWORD dwTextFormat )\r
7226 {\r
7227     this->iFont = iFont;\r
7228     this->dwTextFormat = dwTextFormat;\r
7229 \r
7230     FontColor.Init( defaultFontColor );\r
7231 }\r
7232 \r
7233 \r
7234 //--------------------------------------------------------------------------------------\r
7235 void CDXUTElement::Refresh()\r
7236 {\r
7237     TextureColor.Current = TextureColor.States[ DXUT_STATE_HIDDEN ];\r
7238     FontColor.Current = FontColor.States[ DXUT_STATE_HIDDEN ];\r
7239 }\r
7240 \r
7241 \r