Re[2]: Не работает CreateDialogIndirect
От: programmater  
Дата: 20.02.13 10:25
Оценка: 2 (1) +1
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>Здравствуйте, CEMb, Вы писали:


J>можно создвать диалог в ресурсе потом сдампить этот кусок памяти в массив и запустить из массива заодно посмотреть что не так


Соглашусь с данным советом. От себя добавлю, что сборка Dialog Template-а в памяти — занятие не для слабонервных, и, как бы это помягче выразиться... не для быдлокодеров. Если все же неймется поработать напрямую с Dialog Template-ами, тогда для начала попробуйте загрузить диалоговый ресурс в память через FindResource->LoadResource->LockResource (я правильно понял выражение "сдампить этот кусок памяти в массив" ? ) и создать диалог из таким образом загруженного template-а. Посмотреть, что из этого получится [скорее всего получится]. Потом, в качестве разминки, попытайтесь заменить имя фонта диалога (у вас ведь стоит стиль DS_SETFONT?) и размер фонта. Если сразу не получится [а скорее всего не получится], то внесите поменяйте фонт в ресурсе и посмотрите, как изменился Dialog Template. После того, как научитесь программно менять фонт ресурса (и если Ваш пыл к этому времени не иссякнет) — можно приступать с "сборке диалогового ресурса в памяти". Удачи Вам на этом нелегком пути.
Re[5]: Не работает CreateDialogIndirect
От: Carc Россия http://www.amlpages.com/home.php
Дата: 02.03.13 17:42
Оценка: 4 (1)
Здравствуйте, CEMb, Вы писали:

CEM>Здравствуйте, Carc, Вы писали:


C>>Где то тут на КЫВТ в старых статьях был код, который собирал диалог на лету. Работает и до сих пор. Из плюсов: код достаточно юзабельный, в виде класса. В распоряжении получаете достаточно высокоуровневые функции вида AddControl(тип_контрола, текст, CRect rSize) ну и так далее. Но вот с визуальными стилями этот код не дружил — приходилось ручками добавлять.


CEM>Пальцем покажи где?

Кажется вот он
Автор: SergH
Дата: 20.11.04
. По крайней мере это очень близко, почти с точностью до запятой к тому, что я вижу у себя в старых исходниках одного старинного проекта.
Aml Pages Home
Re[2]: Не работает CreateDialogIndirect
От: jyuyjiyuijyu  
Дата: 19.02.13 07:08
Оценка: 2 (1)
кстати в книге Ганеев Р.М. "Проектирование интерфейса пользователя средствами Win32 API" есть функция которая собирает диалог так как вы хотите
Re: Не работает CreateDialogIndirect
От: Baskak Россия  
Дата: 20.02.13 12:29
Оценка: 2 (1)
Здравствуйте, CEMb, Вы писали:

CEM>Скопировал пример из msdn-а, он не работает

...

Не разобрался еще? Если еще актуально, выложи проект минимальный (желательно VS2008), времени нет а то с нуля делать, я попробую подшаманить, чтоб заработало.
Буквально неделю-две назад занимался подобным вопросом, там правда я CreateDialogIndirect() для создания WTL-ных диалогов использовал, получилось. Так что думаю проблема несложная.

Или вот из своего кода надергал, надеюсь ничего важного не забыл, может и сам разберешься:
  Скрытый текст
static const UINT IDS_LISTTITLE = 101;
static const UINT IDL_LIST = 102;

LPWORD AlignDword(LPWORD lpIn) // align on DWORD bondary
{
    return (LPWORD)(((DWORD)lpIn + 3) & ~3);
}

LPWORD AlignWord(LPWORD lpIn) // align on WORD boundary
{
    return (LPWORD)(((DWORD)lpIn + 1) & ~1);
}

DWORD PushStr(LPWORD szAddr, LPWSTR szStr) // push string to specified address, return number of pushed bytes (include zero-terminator)
{
    DWORD dwLen = wcslen(szStr) + 1;
    CopyMemory(szAddr, szStr, dwLen * sizeof(WCHAR));
    return dwLen;
}

LPDLGTEMPLATE CSelectDlg::CreateDlgTemplate()
{
    // allocate memory
    const int nSize = 1024;
    LPBYTE pBuf = (LPBYTE)malloc(nSize);
    if (!pBuf)
        return NULL;
    SecureZeroMemory(pBuf, nSize);
    LPDLGTEMPLATE lpdt = (LPDLGTEMPLATE)pBuf;
    LPDLGITEMTEMPLATE lpdit = NULL;
    LPWORD lpw = NULL;

    // Define a dialog box
    lpdt->style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU;
    lpdt->dwExtendedStyle = WS_EX_WINDOWEDGE;
    lpdt->cdit = 4; // Number of controls
    lpdt->x = 0; lpdt->y = 0;
    lpdt->cx = 388; lpdt->cy = 169;
    lpw = (LPWORD)(lpdt + 1);
    lpw = AlignWord(lpw); // Align on WORD boundary
    *lpw++ = 0; // No menu
    lpw = AlignWord(lpw); // Align on WORD boundary
    *lpw++ = 0; // Predefined dialog box class (by default)
    lpw = AlignWord(lpw); // Align on WORD boundary
    lpw += PushStr(lpw, L""); // title
    if (lpdt->style & DS_SETFONT)
    {
        lpw = AlignWord(lpw); // Align on WORD boundary
        *lpw++ = 8; // font size
        lpw = AlignWord(lpw); // Align on WORD boundary
        lpw += PushStr(lpw, L"Ms Shell Dlg"); // font family name
    }

    // define top static
    lpw = AlignDword(lpw); // Align DLGITEMTEMPLATE on DWORD boundary
    lpdit = (LPDLGITEMTEMPLATE)lpw;
    lpdit->x = 12; lpdit->y = 6;
    lpdit->cx = 366; lpdit->cy = 8;
    lpdit->id = IDS_LISTTITLE;
    lpdit->style = WS_CHILD | WS_VISIBLE | WS_GROUP | SS_CENTERIMAGE;
    lpw = (LPWORD)(lpdit + 1);
    lpw = AlignWord(lpw); // Align on WORD boundary
    *lpw++ = 0xFFFF;
    *lpw++ = 0x0082; // Static class
    lpw = AlignWord(lpw); // Align on WORD boundary
    lpw += PushStr(lpw, L""); // text
    lpw = AlignWord(lpw); // Align on WORD boundary
    *lpw++ = 0; // No creation data

    // define List control
    lpw = AlignDword(lpw); // Align DLGITEMTEMPLATE on DWORD boundary
    lpdit = (LPDLGITEMTEMPLATE)lpw;
    lpdit->x = 12; lpdit->y = 18;
    lpdit->cx = 366; lpdit->cy = 126;
    lpdit->id = IDL_LIST;
    lpdit->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT;
    lpw = (LPWORD)(lpdit + 1);
    lpw = AlignWord(lpw); // Align on WORD boundary
    lpw += PushStr(lpw, WC_LISTVIEWW);
    lpw = AlignWord(lpw); // Align on WORD boundary
    lpw += PushStr(lpw, L"");
    lpw = AlignWord(lpw); // Align on WORD boundary
    *lpw++ = 0; // No creation data

    // define OK button
    lpw = AlignDword(lpw); // Align DLGITEMTEMPLATE on DWORD boundary
    lpdit = (LPDLGITEMTEMPLATE)lpw;
    lpdit->x = 264; lpdit->y = 150;
    lpdit->cx = 54; lpdit->cy = 14;
    lpdit->id = IDOK;
    lpdit->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON;
    lpw = (LPWORD)(lpdit + 1);
    lpw = AlignWord(lpw); // Align on WORD boundary
    *lpw++ = 0xFFFF;
    *lpw++ = 0x0080; // Button class
    lpw = AlignWord(lpw); // Align on WORD boundary
    lpw += PushStr(lpw, L"OK");
    lpw = AlignWord(lpw); // Align on WORD boundary
    *lpw++ = 0; // No creation data

    // define Cancel button
    lpw = AlignDword(lpw); // Align DLGITEMTEMPLATE on DWORD boundary
    lpdit = (LPDLGITEMTEMPLATE)lpw;
    lpdit->x = 324; lpdit->y = 150;
    lpdit->cx = 54; lpdit->cy = 14;
    lpdit->id = IDCANCEL;
    lpdit->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON;
    lpw = (LPWORD)(lpdit + 1);
    lpw = AlignWord(lpw); // Align on WORD boundary
    *lpw++ = 0xFFFF;
    *lpw++ = 0x0080; // Button class
    lpw = AlignWord(lpw); // Align on WORD boundary
    lpw += PushStr(lpw, L"Отмена");
    lpw = AlignWord(lpw); // Align on WORD boundary
    *lpw++ = 0; // No creation data

    // ready
    return lpdt;
}
Re: Не работает CreateDialogIndirect
От: jyuyjiyuijyu  
Дата: 19.02.13 06:53
Оценка: +1
Здравствуйте, CEMb, Вы писали:

можно создвать диалог в ресурсе потом сдампить этот кусок памяти в массив и запустить из массива заодно посмотреть что не так
Не работает CreateDialogIndirect
От: CEMb  
Дата: 19.02.13 05:27
Оценка:
Скопировал пример из msdn-а, он не работает
GetLastError = 0
Список возможные причины несрабатывания из msdn-а — ни одна не подходит.


BOOL DialogBoxProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_INITDIALOG:
        return TRUE;
        break;
    case WM_COMMAND:
        {
            int wmId, wmEvent;
            wmId    = LOWORD(wParam);
            wmEvent    = HIWORD(wParam); 
            switch(wmId)
            {
            case IDOK:
            case IDCANCEL:
                EndDialog(hWnd, wmId);
                break;
            }
        }
        break;
    }
    return 0;
}


    HGLOBAL hgbl;
    LPDLGTEMPLATE lpdt;
    LPDLGITEMTEMPLATE lpdit;
    LPWORD lpw;
    LPWSTR lpwsz;
    LRESULT ret;
    int nchar;

    hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
    if (!hgbl)
        return NULL;
 
    lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
 
    // Define a dialog box.
 
    lpdt->style = WS_BORDER | DS_MODALFRAME | WS_SYSMENU | WS_CAPTION;

/* ВОТ ТУТ */
    lpdt->cdit = 1;  // number of controls


    lpdt->x  = 0;  lpdt->y  = 5;
    lpdt->cx = 120; lpdt->cy = 25;

    lpw = (LPWORD) (lpdt + 1);
    *lpw++ = 0;   // no menu
    *lpw++ = 0;   // predefined dialog box class (by default)

    lpwsz = (LPWSTR) lpw;
    nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "A?", -1, lpwsz, 50);
    lpw   += nchar;


    //-----------------------
    // Define an OK button.
    //-----------------------
    lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
    lpdit = (LPDLGITEMTEMPLATE) lpw;
    lpdit->x  = 10; lpdit->y  = 70;
    lpdit->cx = 80; lpdit->cy = 20;
    lpdit->id = IDOK;  // OK button identifier
    lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;

    lpw = (LPWORD) (lpdit + 1);
    *lpw++ = 0xFFFF;
    *lpw++ = 0x0080;    // button class

    lpwsz = (LPWSTR) lpw;
    nchar = 1+MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
    lpw   += nchar;
    lpw = lpwAlign (lpw); // align creation data on DWORD boundary
    *lpw++ = 0;           // no creation data


    GlobalUnlock(hgbl); 
    HWND hRes = CreateDialogIndirect(GetModuleHandle(NULL), (LPDLGTEMPLATE) hgbl, hwndOwner, (DLGPROC) DialogBoxProc); 
    GlobalFree(hgbl);

    return hRes;


Вот если контролов нету, т.е. lpdt->cdit = 0; то диалог создаётся, если lpdt->cdit = 1; то нет
В примере было три контрола, но я урезал до одного.

При вызове сразу прилетает wm_destroy & wm_ncdestroy
Re: Не работает CreateDialogIndirect
От: Аноним  
Дата: 19.02.13 06:13
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM> HWND hRes = CreateDialogIndirect(GetModuleHandle(NULL), (LPDLGTEMPLATE) hgbl, hwndOwner, (DLGPROC) DialogBoxProc);


а вы, кстати, в курсе, что Proc у CreateDialog и DialogBox несколько не совпадают ?
Re[2]: Не работает CreateDialogIndirect
От: CEMb  
Дата: 19.02.13 16:16
Оценка:
Здравствуйте, Аноним, Вы писали:

CEM>> HWND hRes = CreateDialogIndirect(GetModuleHandle(NULL), (LPDLGTEMPLATE) hgbl, hwndOwner, (DLGPROC) DialogBoxProc);


А>а вы, кстати, в курсе, что Proc у CreateDialog и DialogBox несколько не совпадают ?


На самом деле изначально там DialogBoxIndirect, который я и проверял. Уже потом, перед тем, как постить сюда, я начал функцию переписывать, потом решил запостить кусок кода, этот момент забыл вернуть назад

Изначально я взял весь кусок кода из msdn-а, не компилируя переделал те три контрола на свои — на заработало. Упростил — не заработало. Удалил всё нафиг и вставил опять код из msdn-а — не заработало, с одинм контролом — не заработало! Ну а дальше знаете уже
Re[3]: Не работает CreateDialogIndirect
От: Carc Россия http://www.amlpages.com/home.php
Дата: 20.02.13 12:45
Оценка:
Здравствуйте, programmater, Вы писали:

P>Здравствуйте, jyuyjiyuijyu, Вы писали:


J>>Здравствуйте, CEMb, Вы писали:


J>>можно создвать диалог в ресурсе потом сдампить этот кусок памяти в массив и запустить из массива заодно посмотреть что не так


P>Соглашусь с данным советом. От себя добавлю, что сборка Dialog Template-а в памяти — занятие не для слабонервных, и, как бы это помягче выразиться... не для быдлокодеров. Если все же неймется поработать напрямую с Dialog Template-ами, тогда для начала попробуйте загрузить диалоговый ресурс в память через FindResource->LoadResource->LockResource (я правильно понял выражение "сдампить этот кусок памяти в массив" ? ) и создать диалог из таким образом загруженного template-а. Посмотреть, что из этого получится [скорее всего получится]. Потом, в качестве разминки, попытайтесь заменить имя фонта диалога (у вас ведь стоит стиль DS_SETFONT?) и размер фонта. Если сразу не получится [а скорее всего не получится], то внесите поменяйте фонт в ресурсе и посмотрите, как изменился Dialog Template. После того, как научитесь программно менять фонт ресурса (и если Ваш пыл к этому времени не иссякнет) — можно приступать с "сборке диалогового ресурса в памяти". Удачи Вам на этом нелегком пути.

Где то тут на КЫВТ в старых статьях был код, который собирал диалог на лету. Работает и до сих пор. Из плюсов: код достаточно юзабельный, в виде класса. В распоряжении получаете достаточно высокоуровневые функции вида AddControl(тип_контрола, текст, CRect rSize) ну и так далее. Но вот с визуальными стилями этот код не дружил — приходилось ручками добавлять.
Aml Pages Home
Re[2]: Не работает CreateDialogIndirect
От: CEMb  
Дата: 20.02.13 16:06
Оценка:
Здравствуйте, Baskak, Вы писали:

B>Не разобрался еще?


Не, но думаю, я дамп посмотрю, как выше написано, я примерную схему по коду знаю. Заодно пройду тест на быдлокодера

Задача была у меня такая:
У меня был контрол, лист-дерево, с кнопками-иконками в разных местах.
И тут меня смутили ближние люди, сказав: "окно настроек с таб-контролами — это прошлый век, это не расширяемо, это ненаглядно, это..."
Я подумал и сделал окно настроек так: бросил слева типа дерево, а справа лист.
В дерево тыкаешься — лист перезаполняется по контенту.
И тут встала проблема — лист из необходимого поддерживал только чеки(чекбоксы), другое было ненужно раньше, чеки были реализованы внутри листа и были рерурсонезависимы, что важно (чтоб легко перетаскивать контрол из проекта в проект).
С другой стороны, у меня есть небольшая система параметров — шаблонов, которые можно привязывать быстро привязывать к реестру и контролам, собирать в множества и т.д. И так как через них я делал настройки, захотелось это всё к листу добавить. Но такому параметру при настройке нужна была привязка к ресурсу. Ну, например, есть параметр [0..100], есть диалог настроек. Я кидаю туда едит, спин и слайдер, на каждый контрол привязываю этот параметр, и все три контрола становятся связаны с параметром и между собой (меняешь слайдер — меняется текст, меняешь спин — меняется текст и слайдер, удобно! причём "смешать" так можно скоко угодно элементов).
И вот мне захотелось на числовые параметры иметь на листе такие мини-диалоги, которые не надо описывать в ресурсах. И первое, что вспомнилось — CreateDialogIndirect. Вобщем, так как времени разбираться не было, я всё пока сделал через CreateWindowEx, но это не айс, по понятным причинам. Так что буду смотреть в дамп. Или, ещё более простой вариант (мне ж константный диалог нужен) — соберу в ресурсах нужный диалог, сниму дамп и пропишу побайтно в коде
Re[4]: Не работает CreateDialogIndirect
От: CEMb  
Дата: 20.02.13 16:08
Оценка:
Здравствуйте, Carc, Вы писали:

C>Где то тут на КЫВТ в старых статьях был код, который собирал диалог на лету. Работает и до сих пор. Из плюсов: код достаточно юзабельный, в виде класса. В распоряжении получаете достаточно высокоуровневые функции вида AddControl(тип_контрола, текст, CRect rSize) ну и так далее. Но вот с визуальными стилями этот код не дружил — приходилось ручками добавлять.


Пальцем покажи где?
Re[3]: Не работает CreateDialogIndirect
От: jyuyjiyuijyu  
Дата: 20.02.13 18:30
Оценка:
Здравствуйте, programmater, Вы писали:

FindResource->LoadResource->LockResource (я правильно понял выражение "сдампить этот кусок памяти в массив" ?

можно еще так взять Restorator или другой менеджер ресурсов распаковать нужный диалог в файл потом открыть этот файл в WinHex там есть такая опция сохранить как C/C++ массив

потом этот массив скормить CreateDialogIndirect
Re[4]: Не работает CreateDialogIndirect
От: CEMb  
Дата: 21.02.13 02:18
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>FindResource->LoadResource->LockResource (я правильно понял выражение "сдампить этот кусок памяти в массив" ?


вот пример (загрузка картинки из ресурсов напрямую):


BOOL LoadPictureRes(LPPICTURE &lpPicture, LPCTSTR ID, LPCTSTR lpctType)
{
    HINSTANCE hInst = GetModuleHandle(NULL);
    // open file
    HRSRC hPic = FindResource(hInst, (LPCTSTR)ID, lpctType);
    
    HGLOBAL hResData;
    if (!hPic || !(hResData = LoadResource(hInst, hPic)))
    {
        return FALSE;
    };

    // open resource
    DWORD dwSize = SizeofResource(hInst, hPic);
    HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, dwSize);
    if (!hGlobal)
    {
        FreeResource(hResData);
        return FALSE;
    };

    LPVOID pvData = NULL;
    pvData = GlobalLock(hGlobal);
    char *pSrc = reinterpret_cast<char *> (LockResource(hResData));
    if (!pSrc || !pvData)
    {
        GlobalFree(hGlobal);
        FreeResource(hResData);
        return FALSE;
    };
    CopyMemory((BYTE*)pvData, pSrc, dwSize);

    GlobalUnlock(hGlobal);
    FreeResource(hResData);

    LPSTREAM pstm = NULL;
    HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);

    // Create IPicture from image file
    if (lpPicture)    
        (lpPicture)->Release();

    hr = OleLoadPicture(pstm, dwSize, FALSE, IID_IPicture, (LPVOID *)&lpPicture);
    pstm->Release();
    _ASSERTE(SUCCEEDED(hr) && lpPicture);    
    if(!SUCCEEDED(hr) || NULL == pvData)
        return FALSE;
    return TRUE;
}
Re: Не работает CreateDialogIndirect
От: Pavel Dvorkin Россия  
Дата: 21.02.13 03:38
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Вот если контролов нету, т.е. lpdt->cdit = 0; то диалог создаётся, если lpdt->cdit = 1; то нет

CEM>В примере было три контрола, но я урезал до одного.

CEM>При вызове сразу прилетает wm_destroy & wm_ncdestroy


Какие именно контролы ? Не common controls ? Если да — вызвана ли InitCommonControls ?
With best regards
Pavel Dvorkin
Re[2]: Не работает CreateDialogIndirect
От: CEMb  
Дата: 21.02.13 07:01
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Какие именно контролы ? Не common controls ? Если да — вызвана ли InitCommonControls ?


Кнопки, я пример кода привёл, там button. И их тоже пробовал. Вызвана.
Re[3]: Не работает CreateDialogIndirect
От: programmater  
Дата: 21.02.13 15:40
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Здравствуйте, Baskak, Вы писали:


B>>Не разобрался еще?


CEM>Не, но думаю, я дамп посмотрю, как выше написано, я примерную схему по коду знаю. Заодно пройду тест на быдлокодера


CEM>Задача была у меня такая:

CEM>У меня был контрол, лист-дерево, с кнопками-иконками в разных местах.
CEM>И тут меня смутили ближние люди, сказав: "окно настроек с таб-контролами — это прошлый век, это не расширяемо, это ненаглядно, это..."
CEM>Я подумал и сделал окно настроек так: бросил слева типа дерево, а справа лист.
CEM>В дерево тыкаешься — лист перезаполняется по контенту.
CEM>И тут встала проблема — лист из необходимого поддерживал только чеки(чекбоксы), другое было ненужно раньше, чеки были реализованы внутри листа и были рерурсонезависимы, что важно (чтоб легко перетаскивать контрол из проекта в проект).
CEM>С другой стороны, у меня есть небольшая система параметров — шаблонов, которые можно привязывать быстро привязывать к реестру и контролам, собирать в множества и т.д. И так как через них я делал настройки, захотелось это всё к листу добавить. Но такому параметру при настройке нужна была привязка к ресурсу. Ну, например, есть параметр [0..100], есть диалог настроек. Я кидаю туда едит, спин и слайдер, на каждый контрол привязываю этот параметр, и все три контрола становятся связаны с параметром и между собой (меняешь слайдер — меняется текст, меняешь спин — меняется текст и слайдер, удобно! причём "смешать" так можно скоко угодно элементов).
CEM>И вот мне захотелось на числовые параметры иметь на листе такие мини-диалоги, которые не надо описывать в ресурсах. И первое, что вспомнилось — CreateDialogIndirect. Вобщем, так как времени разбираться не было, я всё пока сделал через CreateWindowEx, но это не айс, по понятным причинам. Так что буду смотреть в дамп. Или, ещё более простой вариант (мне ж константный диалог нужен) — соберу в ресурсах нужный диалог, сниму дамп и пропишу побайтно в коде
Мне всегда говорили, что половина решения задачи содержится в правильной ее (задачи) постановке. Похоже что ты ринулся решать второстепенную проблему (создание диалога из памяти), до конца не продумав главную. Идея снабдить ListView шибко крутым интерфейсом напихав в него дочерних контролов (Ого! Ты даже до дочерних диалогов додумался! ) кажется привлекательной. Но только на первый взгляд. Ну допустим, научился ты создавать свои диаложки и напихал их в ListView, а дальше что? В общем дам тебе две проблемы, которые... [я в свое время решить не смог, поэтому отказался от этой идеи]. Что будешь делать в случае:
1. Сжатия/расширения SubItem-ов тасканием за Header (полностью решается только убийством хидера на корню: нет хидера — нет проблемы )
2. ScrollBar-ы в твоем ListView. Ну как, скажи мне, ты собрался перетаскивать дочерние диалоги согласно тасканию пимпочки на скролбаре? А клавиатурный скрол не забыл?
3. А если строчек 10 тыщ? Система не охренеет от такого количества дочерних диалогов?

В общем после размышлений я выбрал более-менее стандартную в таких случаях схему: Лист оставляем листом как есть, все эффекты делаем чезез StateImages (элементарно) / NM_CUSTOMDRAW (для продвинутых), а контрольчики (точнее один-единственный контрольчик) создаем в момент клика по SubItem-у и прямо на месте этого SubItem-а. После того, как юзер отредактировал элемент, достаем данные и з контрольчика, запихиваем их в лист и прибиваем контрольчик нахрен [Подсказка для быдлокодеров:
  Скрытый текст
"прбиваем контрольчик нахрен" означает
::PostMessage(hWndControl, WM_CLOSE, 0, 0);

Не вздумай вызывать DestroyWindow в обработчике нотификации от этого контрола! Почему? Ну, когда программа рухнет — поймешь
]. При такой схеме набор контрольчиков существенно ограничен, но кое на что сгодится и такой. Что можно сделать?
1. Чекбоксы и радиобоксы. Элементарно делаются через StateImages. Обработка кликов (и изменение состояния по этим кликам) — самому. Но не так уж это и сложно.
2. Обыкновенный edit. Тоже все понятно. Кликнули->создали контрол->по Enter сохранили данные в Листе, по Esc или потере фокуса (важно!) просто прибили этот edit.
3. Комбо бокс. В общем то же самое, что и edit. Просто комбобокс после создания сразу раскрываешь. Если хочешь, чтобы выглядело все "по крутому" (т.е. чтобы у всех айтемов справа была кнопочка со стрелочкой как у нормальных свернутых комбобоксов) — делаешь это через CustomDraw [чем не тест на быдлокодера?]. С потерей фокуса немного сложнее, но подскажу: лови CBN_SELENDOK и CBN_SELENDCANCEL. Если все правильно сделаешь — этих двух сообщений будет достаточно.
4. Спин — туда же, куда и комбо. Сам не пробовал, так что как там с фокусом не подскажу, исследуй сам.
5. Кнопки. Не знаю, зачем они в листе, но если очень надо — NM_CUSTOMDRAW + DrawFrameControl. Клики — самому.
От слайдеров думаю придется отказаться. С ходу не придумаю как их туда воткнуть.
В общем как-то так. Ну или если решишь как быть со скролами/хидерами — напиши мне как.
Re[4]: Не работает CreateDialogIndirect
От: CEMb  
Дата: 21.02.13 17:33
Оценка:
Здравствуйте, programmater, Вы писали:

P>Мне всегда говорили, что половина решения задачи содержится в правильной ее (задачи) постановке. Похоже что ты ринулся решать второстепенную проблему (создание диалога из памяти), до конца не продумав главную. Идея снабдить ListView шибко крутым интерфейсом напихав в него дочерних контролов (Ого! Ты даже до дочерних диалогов додумался! )


Хмм.
Вообще я сейчас вспомнил, что первый раз до такой штуки я додумался и реализовал более 10 лет назад, когда писал конвертеры для баз данных. Там надо было на ходу накидывать входящие поля и выбирать куда они будут перекочёвывать. Окно-контейнер имело скролл-бар и динамический набор дочерних диалогов, с кнопками управления и комбобоксом со списком полей экспортируемой базы данных.
И ещё один момент — это не ListView, он мне не подходит. Точнее, в процессе разработок я сделал свой лист-дерево, поэтому мне удобнее его использовать.

P>кажется привлекательной. Но только на первый взгляд. Ну допустим, научился ты создавать свои диаложки и напихал их в ListView, а дальше что? В общем дам тебе две проблемы, которые... [я в свое время решить не смог, поэтому отказался от этой идеи]. Что будешь делать в случае:

P>1. Сжатия/расширения SubItem-ов тасканием за Header (полностью решается только убийством хидера на корню: нет хидера — нет проблемы )
У меня нету сабитемов, за ненадобностью.
P>2. ScrollBar-ы в твоем ListView. Ну как, скажи мне, ты собрался перетаскивать дочерние диалоги согласно тасканию пимпочки на скролбаре? А клавиатурный скрол не забыл?
Не забыл, это давно уже сделано, есть скролливание под фокус при клавиатурном вводе. Так как задумывалось дерево, я сделал возможность добавить тул-разрёртыш (который в обычном дереве [+], сначала и у меня был [+], но люди сказали "щас так не модно, модно кнопка с шевроном"... ну, блин, вот теперь у меня кнопка с аппаратным шевроном по умолчанию... хотя можно на неё влепить любую картинку на каждое состояние). Плюс, само наличие диалогов я заложил в лист изначально, где-то это даже использовалось. Диалог в итеме не виден, пока expand не нажмёшь. Там же под экспандом сидят дочерние итемы. Скроллбары работают. У меня ещё есть возможность обратного порядка заполнения, от низа к верху, как в фотошопе. Кроме скролинга у меня присутствует expand и ресайзинг и диалоги на дочерних итемах. И каждому итему можно задать персональную высоту. И всё это учитывается при скролинге, expand-е и ресайзе. Expand/collapse/переход на парента — с клавиатуры тоже можно. (Multi)выделение с shift/ctrl. Есть драг-н-дроп(но для дерева ещё не доделан нормально), с подсветкой. И весь этот зоопарк нотифаит родительское окно по клаве/мыши/change/command/drop и имеет возможность внешнего расширения итемов, так что можно делать навороты дальше, не меняя основной класс окна. Я не первый год делаю свои окна. Так что всё ок.
P>3. А если строчек 10 тыщ? Система не охренеет от такого количества дочерних диалогов?
Охренеет ещё на трёх тысячах, в моём случае, но мне пока надо штук 10 максимум. По хорошему, конечно, надо динамически их создавать, но будем решать проблемы по мере их поступления(к тому же статика ближе к вышеописанной системе шаблонов-параметров, которые биндятся на старте). Три-четыре проекта назад я решил эту проблему просто подъёмом отдельных больших диалогов с настройками, так как настроек там было дофигищи на каждый итем, 2-4 закладки, с некоторых ещё диалоги поднимались... так что этот зоопарк в лист не влез бы. Но сейчас всё по-другому, один итем — оди параметр, а то я бы и сейчас сделал так же, но для одного параметра как-то странно подымать диалог.

P>В общем после размышлений я выбрал более-менее стандартную в таких случаях схему: Лист оставляем листом как есть, все эффекты делаем чезез StateImages (элементарно) / NM_CUSTOMDRAW (для продвинутых), а контрольчики (точнее один-единственный контрольчик) создаем в момент клика по SubItem-у и прямо на месте этого SubItem-а. После того, как юзер отредактировал элемент, достаем данные и з контрольчика, запихиваем их в лист и прибиваем контрольчик нахрен [Подсказка для быдлокодеров:
  Скрытый текст
"прбиваем контрольчик нахрен" означает
P>
P>::PostMessage(hWndControl, WM_CLOSE, 0, 0);
P>

P> Не вздумай вызывать DestroyWindow в обработчике нотификации от этого контрола! Почему? Ну, когда программа рухнет — поймешь
].

А так я делал восемь-девять лет назад, когда надо было копировать свойства окна из таблички. Программа была на MFC, контрол я не убивал, а скрывал, потому как он был mfc-шный и сам создавался/убивался вместе с окном свойств.
P>При такой схеме набор контрольчиков существенно ограничен, но кое на что сгодится и такой. Что можно сделать?
P>[...]
Эту схему уже те же 10 лет мы используем на работе, только не на ListView а на другой таблице, но принцип тот же. Только спинов у нас нету, так как не нужны, а кнопки и чеки у этой таблицы штатные. Остальное ровно так же.

P>От слайдеров думаю придется отказаться. С ходу не придумаю как их туда воткнуть.

да слайдер-то туда можно воткнуть и обработать, проблема в том, что он не информативен сам по себе. Нужен сбоку едит/статик, который показывает, каково значение на данный момент. А на едите полезен спин, чтоб сразу колесом его менять. Сразу получаем те самые три контрола.
P>В общем как-то так. Ну или если решишь как быть со скролами/хидерами — напиши мне как.
С хидерами проблему можно попробовать решить через нотификации, хедер при смене размера-положения заголовков шлёт нотификации родителю. Я на это раньше затачивался, у меня была таблица, во второй колонке были числовые значения, и чтоб сэкономить место, я размещал там кнопку-чек "hex", при нажатии на которую значение выводилось в 16-м виде, при отжатии — в 10-м. Вот чтоб размещать кнопку в правильном месте, затачивался на нотификации от хедера. Но вот не помню, получилось у меня это полностью сделать или нет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.