source: dev/branches/egtra/ab5.0/abdev/abdev-impl/Resource/Load.cpp@ 791

Last change on this file since 791 was 791, checked in by イグトランス (egtra), 13 years ago

LoadAccelerators代替関数の実装

File size: 4.1 KB
Line 
1#include "stdafx.h"
2#include <vector>
3#include <utility>
4#include <boost/range.hpp>
5#include <boost/range/adaptor/transformed.hpp>
6#include <boost/numeric/conversion/cast.hpp>
7#include <Resource/Load.h>
8
9using boost::numeric_cast;
10
11namespace ActiveBasic { namespace Resource {
12
13namespace {
14
15template<typename Map, typename Key, typename AddValueFunctor>
16typename Map::iterator GetCacheFromMap(Map& map, Key key, AddValueFunctor f)
17{
18 auto low = map.lower_bound(key);
19 if (low != map.end() && map.key_comp()(key, low->first))
20 {
21 return low;
22 }
23 else
24 {
25 typedef typename Map::key_type key_type;
26 typedef typename Map::value_type value_type;
27 return map.insert(low, std::make_pair(std::move(key), f()));
28 }
29}
30
31void* GetResource(HINSTANCE hinst, USHORT id, LPCTSTR type)
32{
33 if (auto hrsrc = ::FindResource(hinst, MAKEINTRESOURCE(id), type))
34 {
35 if (auto hSrc = ::LoadResource(hinst, hrsrc))
36 {
37 return ::LockResource(hSrc);
38 }
39 }
40 return nullptr;
41}
42
43std::pair<void*, DWORD> GetResourceWithSize(HINSTANCE hinst, USHORT id, LPCTSTR type)
44{
45 typedef std::pair<void*, DWORD> result_type;
46 if (auto hrsrc = ::FindResource(hinst, MAKEINTRESOURCE(id), type))
47 {
48 if (auto hSrc = ::LoadResource(hinst, hrsrc))
49 {
50 auto p = ::LockResource(hSrc);
51 auto size = ::SizeofResource(hinst, hrsrc);
52 if (p != nullptr && size > 0)
53 {
54 return result_type(p, size);
55 }
56 }
57 }
58 return result_type(nullptr, 0);
59}
60
61HICON LoadIconCursorImpl(HINSTANCE hinst, USHORT id, int cxDesired, int cyDesired, UINT load, bool isIcon)
62{
63 auto pResource = GetResource(hinst, id, isIcon ? RT_GROUP_ICON : RT_GROUP_CURSOR);
64
65 auto idIcon = LookupIconIdFromDirectoryEx(reinterpret_cast<PBYTE>(pResource), isIcon, cxDesired, cyDesired, load);
66 auto icon = GetResourceWithSize(hinst, numeric_cast<USHORT>(idIcon), isIcon ? RT_ICON : RT_CURSOR);
67
68 return CreateIconFromResourceEx(reinterpret_cast<PBYTE>(icon.first),
69 icon.second, isIcon, 0x00030000, cxDesired, cyDesired, load);
70}
71
72}
73
74HICON LoadIcon(HINSTANCE hinst, USHORT id, int cxDesired, int cyDesired, UINT load)
75{
76 return LoadIconCursorImpl(hinst, id, cxDesired, cyDesired, load, true);
77}
78
79HICON LoadIcon(HINSTANCE hinst, USHORT id)
80{
81 return LoadIconCursorImpl(hinst, id, 32, 32, LR_SHARED, true);
82}
83
84HCURSOR LoadCursor(HINSTANCE hinst, USHORT id)
85{
86 return LoadIconCursorImpl(hinst, id, 32, 32, LR_SHARED, false);
87}
88
89// 文字列リソースの読み込みについては以下を参照。
90// How To Use LoadResource to Load Strings from a String Table
91// http://support.microsoft.com/kb/200893/en-us
92boost::optional<std::wstring> LoadString(HINSTANCE hinst, USHORT id)
93{
94 UINT idRsrcBlk = id / 16 + 1;
95 int strIndex = id % 16;
96
97 auto hrsrc = FindResourceEx(hinst, RT_STRING, MAKEINTRESOURCE(idRsrcBlk), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
98 if (hrsrc == nullptr)
99 return boost::none;
100
101 auto hRes = LoadResource(hinst, hrsrc);
102 if (hRes == nullptr)
103 return boost::none;
104 LPCWSTR p = static_cast<LPCWSTR>(LockResource(hRes));
105 if (p == nullptr)
106 return boost::none;
107
108 for (int i = 0; i < strIndex; ++i)
109 {
110 UINT length = *p++;
111 p += length;
112 }
113
114 UINT cch = *p++;
115 if (cch == 0)
116 {
117 return boost::none;
118 }
119 else
120 {
121 return std::wstring(p, cch);
122 }
123}
124
125// http://msdn.microsoft.com/en-us/library/ms648010.aspx
126struct ACCELTABLEENTRY
127{
128 WORD fFlags;
129 WORD wAnsi;
130 WORD wId;
131 WORD padding;
132};
133
134ACCEL AccelFromEntry(ACCELTABLEENTRY const& e)
135{
136 ACCEL t = {e.fFlags & 0x7f, e.wAnsi, e.wId};
137 return t;
138}
139
140HACCEL LoadAccelerators(HINSTANCE hinst, USHORT id)
141{
142 using namespace boost::adaptors;
143
144 auto accel = GetResourceWithSize(hinst, id, RT_ACCELERATOR);
145 if (accel.first == nullptr)
146 {
147 return nullptr;
148 }
149
150 auto pate = static_cast<ACCELTABLEENTRY const*>(accel.first);
151
152 auto a = boost::copy_range<std::vector<ACCEL>>(
153 boost::make_iterator_range(pate, pate + accel.second / sizeof (ACCELTABLEENTRY))
154 | transformed(AccelFromEntry));
155
156 if (a.size() > INT_MAX)
157 {
158 a.resize(INT_MAX);
159 }
160 return CreateAcceleratorTable(&a[0], static_cast<int>(a.size()));
161}
162
163}}
164
Note: See TracBrowser for help on using the repository browser.