Page 1 of 1
Dotaz na CSalamanderGeneralAbstract::FocusNameInPanel
Posted: 16 Jan 2009, 11:08
by zarevak
Dobrý den,
mám drobný dotaz ohledně metody CSalamanderGeneralAbstract::FocusNameInPanel(...)
v komentáři (SDK 2.51) je napsáno, že musí byt použita pouze v hlavním vlákně. Jak toho dosáhnu? Hlavní vlákno ve svém pluginu použiju jen ve chvíli, kdy uživatel klikne na položku menu v Salamanderu.
Struktura pluginu je:
hlavní vlákno:
- Zpracovává menu položku a založí UI vlákno
UI vlákno:
- vytvoří okno a pak ho obsluhuje pomocí své message loop
- pokud potřebuje, tak si založí pracovní vlákna
pomocná pracovní vlákna
- komunikují s UI vláknem pomocí sdílených zámků a posílaní WM_APP + n zpráv
Posted: 16 Jan 2009, 12:05
by Petr Solin
Volani v hlavnim vlakne obvykle zajistujeme pres metodu PostMenuExtCommand. Doporucene schema provedeni prikazu Focus ve vieweru je patrne z nasledujiciho kodu (fileName je plne jmeno souboru pro focus v panelu, FocusPathBuf je globalni buffer o velikosti MAX_PATH, MENU_CMD_FOCUS je konstanta s cislem prikazu menu viz PostMenuExtCommand):
Code: Select all
if (SalamanderGeneral->SalamanderIsNotBusy(NULL))
{
lstrcpyn(FocusPathBuf, fileName, MAX_PATH);
SalamanderGeneral->PostMenuExtCommand(MENU_CMD_FOCUS, TRUE);
Sleep(500); // dojde k prepnuti do panelu, takze toto cekani bude v neaktivnim okne vieweru, tedy nicemu nevadi
FocusPathBuf[0] = 0; // po 0.5 sekunde uz o fokus nestojime (resi pripad, kdy jsme trefili zacatek BUSY rezimu Salamandera)
}
else
SalamanderGeneral->SalMessageBox(HWindow, LoadStr(IDS_SAL_IS_BUSY), TITLE_NAME, MB_ICONINFORMATION);
V metode CPluginInterfaceForMenuExt::ExecuteMenuItem osetrime prikaz MENU_CMD_FOCUS:
Code: Select all
case MENU_CMD_FOCUS:
{
char focusPath[MAX_PATH];
lstrcpyn(focusPath, FocusPathBuf, MAX_PATH);
FocusPathBuf[0] = 0;
if (focusPath[0] != 0) // jen pokud jsme nemeli smulu (netrefili jsme zacatek BUSY rezimu Salamandera)
{
LPTSTR name;
if (SalamanderGeneral->CutDirectory(focusPath, &name))
{
SalamanderGeneral->SkipOneActivateRefresh(); // hlavni okno pri prepnuti z viewru nebude delat refresh
SalamanderGeneral->FocusNameInPanel(PANEL_SOURCE, focusPath, name);
}
}
return TRUE;
}
Posted: 16 Jan 2009, 12:09
by Petr Solin
Jeste priklad chybove hlasky:
Code: Select all
IDS_SAL_IS_BUSY, "Altap Salamander is busy. The requested command cannot be accomplished, please try it again later."
Posted: 16 Jan 2009, 13:00
by zarevak
Díky! Sice je to krkolomné řešení, ale funguje
Šlo by do budoucna toto nějak vyřešit čistěji?
(založit metodu pro příjem zpráv v hlavním vlákně včetně nějakého lParam, abychom se zbavili globálních proměnných)
Aby se neměnilo rozhranní, tak by možná stačilo přidat jen možnost posílat zprávy do existující a povinné
CPluginInterface::Event(int event, DWORD param) metody. Jen by mohlo hrozit, že by ID události pluginu kolidovalo s budoucím ID nové události Salamandera...
Posted: 16 Jan 2009, 22:02
by Petr Solin
Urcite by to slo, jeste mi to par lidi zopakuje (nejsi prvni) a pujdu to napsat.
Je tam trochu potiz s tim parametrem, pokud by to bylo neco alokovaneho (nebo treba otevreny handle souboru), je potreba nejak vyresit dealokaci/zavreni v pripade, ze se to nestihne dorucit (drive dojde k unloadu pluginu).
Zatim jsem potrebu parametru obchazel takto: udelas si globalni pole struktur, ktery obsahuji vsechny potrebne parametry (klidne alokovane retezce, atd.), kdyz chces postnout prikaz, nejprve naplnis jednu polozku do toho pole, a pak teprve postnes prikaz (s jednim vybranym ID), az prikaz dojde, vyzvednes si tu polozku z pole a s ni vsechny parametry, a pak prvek pole zrusis. Kdyz dojde k unloadu pluginu, zrusis vsechny zbyle prvky pole (tim se elegantne resi ten zmineny problem s unloadem). Prirozene muzes pri prijmu prikazu vycerpat vsechny prvky pole, aby se provedly co nejdrive, pri prijmu dalsich prikazu menu uz pak nebudes delat nic (pole bude prazdne). Pokud by tech prikazu bylo enormni mnozstvi, muzes i tohle vyoptimalizovat (neposilat dalsi prikaz se stejnym ID dokud predchozi odeslany nedorazil).