Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.217.182.45] |
|
Сообщ.
#1
,
|
|
|
Добрый день. Никак не могу разобраться с функцией FindResource. Есть в моей программе ресурс типа String Table.
Файл ресурсов *rc // Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Русский (Россия) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // String Table // STRINGTABLE BEGIN IDS_HELLO "Hello world!" END #endif // Русский (Россия) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED resource.h //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by LoadString.rc // #define IDS_HELLO 105 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif ну и сам код, который не работает VOID WINAPI LoadStringFromRes() { HRSRC hRes = NULL; HINSTANCE hInstance; hInstance = GetModuleHandle(0); hRes = FindResource(hInstance, MAKEINTRESOURCE(IDS_HELLO), RT_STRING); if(hRes) { printf("FindResource YES"); } else { printf("FindResource Error 0x%x\n", GetLastError()); } } Никак не могу понять, почему FindResource не может найти мою строку. Каждый раз возвращает код ошибки 0x0716 |
Сообщ.
#2
,
|
|
|
Цитата Игорь98 @ Каждый раз возвращает код ошибки 0x0716 Сообщает, что ресурс не найден. Ваша строка ассоциируется с русским языком. Может попробовать использовать FindResourceEx() с указанием русского языка... Добавлено Или попробуйте ещё создать раздел с английским языком и перенести туда ваши строки. |
Сообщ.
#4
,
|
|
|
Игорь98,почитай тут и тут.
Конечно LoadString это хорошо, но мне немного по-другому надо. Попробовал использовать функцию FindResourceEx, с указанием языка, ничего не выходит, все та же ошибка, не может найти. VOID WINAPI LoadStringFromRes() { HRSRC hRes = NULL; HINSTANCE hInstance; hInstance = GetModuleHandle(0); hRes = FindResourceEx(hInstance, RT_STRING, MAKEINTRESOURCE(IDS_HELLO), MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT)); if(hRes) { printf("FindResourceEx YES"); } else { printf("FindResourceEx Error 0x%x\n", GetLastError()); } } Так же попробовал добавить раздел с английским языком // Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Русский (Россия) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // String Table // STRINGTABLE BEGIN IDS_HELLO "Hello world!" END #endif // Русский (Россия) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Английский (США) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US ///////////////////////////////////////////////////////////////////////////// // // String Table // STRINGTABLE BEGIN IDS_HELLO "Hello world!" END #endif // Английский (США) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED Результат нулевой... |
Сообщ.
#5
,
|
|
|
Там со строками, оказывается, не так всё просто. Вот накатал функцию:
bool LoadStringFromRes(HINSTANCE hInstance, DWORD StringID, _TCHAR *Buffer, size_t &BufferLength) { HRSRC hRes; HGLOBAL hBlock; const _TCHAR *cTable; DWORD dwTableSize; DWORD dwOffset; DWORD dwIndex; DWORD dwStringLen; hRes = FindResource(hInstance, (_TCHAR *)((StringID >> 4) + 1), RT_STRING); if(!hRes) { return false; } StringID = StringID % 16; hBlock = LoadResource(hInstance, hRes); if(!hBlock) { return false; } cTable = (_TCHAR *)LockResource(hBlock); if(!cTable) { return false; } dwTableSize = SizeofResource(hInstance, hRes); if(dwTableSize < 1) { return false; } dwOffset = dwIndex = 0; while(dwOffset < dwTableSize) { if(dwIndex == StringID) { dwStringLen = cTable[dwOffset]; if(dwStringLen > 0) { if(!Buffer) { BufferLength = dwStringLen + 1; // 1 = '\0' } else { if(BufferLength < dwStringLen + 1) { dwStringLen = BufferLength - 1; } else { BufferLength = dwStringLen + 1; } memcpy(Buffer, &(cTable[dwOffset + 1]), dwStringLen * sizeof(_TCHAR)); Buffer[dwStringLen] = _T('\0'); } } else { BufferLength = 0; } break; } dwOffset += cTable[dwOffset] + 1; dwIndex++; } return true; } Пример использования: _TCHAR *chStr = NULL; size_t stStrSize; bool res; res = LoadStringFromRes(hInstance, IDS_HELLO, NULL, stStrSize); if(!res) { return; } // если пустая строка if(stStrSize < 1) { return; } try { chStr = new _TCHAR[stStrSize]; } catch(...) { ; } if(!chStr) { return; } res = LoadStringFromRes(hInstance, IDS_HELLO, chStr, stStrSize); if(!res) { delete [] chStr; return; } // <-- выводим строку delete [] chStr; |
Сообщ.
#6
,
|
|
|
Цитата Игорь98 @ Конечно LoadString это хорошо, но мне немного по-другому надо. А что именно надо ? 1. Можно использовать стандартный тип ресурса - строку. Далее LoadString. 2. Можно использовать тип ресурса, определяемый пользователем. Тогда FindResource и.т.д. На мой взгляд, этих вариантов вполне достаточно. |
Сообщ.
#7
,
|
|
|
Игорь98
Остается только одно - самому написать вручную свою FindResourceByIgor, это не очень сложно. |
Сообщ.
#8
,
|
|
|
Цитата Бублик @ Игорь98 Остается только одно - самому написать вручную свою FindResourceByIgor, это не очень сложно Я уже написал выше |
Сообщ.
#9
,
|
|
|
Цитата artsb @ Я уже написал выше Да ? И чему будет равен "((StringID >> 4) + 1)" если выбрать StringID-и (группы строк в ресурсах) равными 101,102,103,104 ? |
Сообщ.
#10
,
|
|
|
ЫукпШ, я сейчас не буду рассказывать что и как. Я прочитал на эту тему много информации на форумах и накатал функцию. Она рабочая. Можете сами проверить.
Вот, например, такая таблица: STRINGTABLE BEGIN 23 "Hello world! 23" 123 "Hello world! 123" 1123 "Hello world! 1123" 11123 "Hello world! 11123" 11223 "Hello world! 11223" 12123 "Hello world! 12123" END И вот такой код: __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { _TCHAR chStr[1024]; size_t stStrSize; HINSTANCE hInstance = GetModuleHandle(0); Memo1->Lines->Clear(); // string 1 stStrSize = sizeof(chStr) / sizeof(_TCHAR); LoadStringFromRes(hInstance, 23, chStr, stStrSize); Memo1->Lines->Add(chStr); // string 2 stStrSize = sizeof(chStr) / sizeof(_TCHAR); LoadStringFromRes(hInstance, 123, chStr, stStrSize); Memo1->Lines->Add(chStr); // string 3 stStrSize = sizeof(chStr) / sizeof(_TCHAR); LoadStringFromRes(hInstance, 1123, chStr, stStrSize); Memo1->Lines->Add(chStr); // string 4 stStrSize = sizeof(chStr) / sizeof(_TCHAR); LoadStringFromRes(hInstance, 11123, chStr, stStrSize); Memo1->Lines->Add(chStr); // string 5 stStrSize = sizeof(chStr) / sizeof(_TCHAR); LoadStringFromRes(hInstance, 11223, chStr, stStrSize); Memo1->Lines->Add(chStr); // string 6 stStrSize = sizeof(chStr) / sizeof(_TCHAR); LoadStringFromRes(hInstance, 12123, chStr, stStrSize); Memo1->Lines->Add(chStr); } В Memo выводится: Hello world! 23 Hello world! 123 Hello world! 1123 Hello world! 11123 Hello world! 11223 Hello world! 12123 Добавлено И если индексы будут подряд, то тоже всё нормально выводится. |
Сообщ.
#11
,
|
|
|
Цитата artsb @ И если индексы будут подряд, то тоже всё нормально выводится. Не верю. Если взять идентификаторы 101,102,103,104 то ((StringID >> 4) + 1) = 7 для любого из них. Чем четыре разных ресурса отличаются друг от друга ? Значит, в случае успеха поиска hRes будет один и тот же. Дальше даже пробовать не буду. В итоге вместо разных ресурсов будем искать какой-то один. К тому же преобразование ID в указатель на char представляется делом сомнительным. А если я выберу вполне допустимый вариант ID = 0 ? Тогда указатель станет равным 1. На на что указывает такой указатель ? |
Сообщ.
#12
,
|
|
|
ЫукпШ, камрад, ну что ж такое...
Почему вы не хотите просто взять и создать тестовый проект? Я ещё раз говорю: функция рабочая. Цитата ЫукпШ @ Дальше даже пробовать не буду. А вот и зря. Вы даже не разобрались что такое RT_STRING. Этот тип возвращает указатель на блок из 16 строк. Поэтому индекс для всех них будет один и тот же. Этот блок потом просто нужно распарсить и вытащить нужную строку. Если вы не заметили, то я изменяю индекс строки на "локальный": Цитата artsb @ StringID = StringID % 16; В общем, один совет - протестируйте |
Сообщ.
#13
,
|
|
|
Цитата ЫукпШ @ К тому же преобразование ID в указатель на char представляется делом сомнительным. А если заменить это преобразование на MAKEINTRESOURCE, всё ещё сомнительно? |
Сообщ.
#14
,
|
|
|
Цитата artsb @ Вы даже не разобрались что такое RT_STRING. Этот тип возвращает указатель на блок из 16 строк. Да, спасибо. Про блок строк - это я не разобрался. |
Сообщ.
#15
,
|
|
|
Цитата ЫукпШ @ Да, спасибо. Про блок строк - это я не разобрался. Со всеми бывает |