Diskuze: C# TCP / ListView DrawItem ( online status )
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 26 zpráv z 26.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Já bych to řešil asi tak, že bych si udělal pole stavů serverů.
Při vykreslení bys vykreslil ikonku podle stavu serveru, který je uložen v tom poli.
Pingání/připojování na servery pokaždý strč do vlastního vlákna a akorát na konci uprav tu informaci v tom poli stavů.
Nezapomeň, že když do něčeho přistupuješ z víc vláken (pole stavů serverů), musíš to nějak ošetřit - tady třeba přes konstrukci lock.
Promiň, ale to mi jako moc dobrý nápad nepřijde. Protože než se
všechny hodnoty nasypou do pole tak DrawItem už dávno jede. A pak to bude
pořád akorát blikat, já bych potřeboval nějakou metodu, která by upravila
jen ty obrázky, text a rámeček nechat tak, jak je.
Asi jsi mě nepochopil
.
Zezačátku v tom poli máš uložený třeba hodnoty, že se stav
zjišťuje.
Když se mají refreshnout pingy, tak zavoláš nějakou funkci, která (podle
typu) pro každej server spustí nový
vlákno, který zjistí stav a hned po doběhnutí uloží výsledek do toho
pole, takže vlastně zjišťuješ stav všech serverů najednou (ne postupně,
jak jsi to asi pochopil) a nezakousneš tím hlavní vlákno.
A bliká to už teď, není důvod, proč by to pak mělo blikat víc,
problém je nejspíš špatná implementace překreslování.
Zbavíš se toho třeba tak, že si přepíšeš třídu ListView:
class ListViewFixed : System.Windows.Forms.ListView
{
public ListViewFixed()
{
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
}
protected override void OnNotifyMessage(Message m)
{
if(m.Msg != 0x14)
{
base.OnNotifyMessage(m);
}
}
}
To mi vůbec na to blikání nepomohlo xD to bude spíš tím že ten DrawItem jede pořád v kuse ne? Že to bliká jen když po tom rychle jezdím myší tak problikne ten text xD už mě to fakt nebaví normální listview byl parádní a člověk tam chce mít jinej rámeček než defaultní modrý od windowsu a hned takové starosti s tím x(
Blikání by mělo zmizet, pošli, jak to teď máš.
Přinejhorším použij PictureBox a kresli si to sám, pak to blikat nebude
Bliká to proto, že při překreslení se se vykreslí celý pozadí a pak ten item a nejspíš mezi každým tím kreslením se to překreslí i na obrazovku (ne jen do nějakýho bufferu).
no mám to takhle nic moc sem neměnil akorát jsem tam hodil aby se mi vykresloval text manuálně a ne přes e.drawtext();
private void ServerList_DrawItem(object sender, DrawListViewItemEventArgs e)
{
string status = e.Item.Text;
Brush textColor = Brushes.Black;
if (e.Item.Selected == true)
{
ServerList.ForeColor = Color.FromArgb(50, 146, 242); // blue text color
SolidBrush ItemColor = new SolidBrush(Color.FromArgb(51, 51, 51)); // gray ( 51, 51, 51) background color
Color BorderColor = Color.FromArgb(51, 102, 153); // blue ( 51, 102, 153 ) border color
e.Graphics.FillRectangle(ItemColor, e.Bounds.X, e.Bounds.Y, (float)210, e.Bounds.Height - 1); // active border
e.Graphics.DrawRectangle(new Pen(BorderColor), e.Bounds.X, e.Bounds.Y, (float)209, e.Bounds.Height - 1); // normal border
}
else
{
//e.DrawText();
}
Bitmap MyIcon = global::Soulwell___Realmlist_modifer.Properties.Resources.off;
e.Graphics.DrawImage(MyIcon, e.Bounds.Left + 190, e.Bounds.Top + 8, 10, 10);
MyIcon.Dispose();
e.Graphics.DrawString(status, e.Item.Font, textColor, e.Bounds.Left + 2 + 40, e.Bounds.Top + 1);
}
a přidal jsem tam ještě to upravení třídy jak si říkal
class ListViewFixed : System.Windows.Forms.ListView
{
public ListViewFixed()
{
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
}
protected override void OnNotifyMessage(Message m)
{
if(m.Msg != 0x14)
{
base.OnNotifyMessage(m);
}
}
}
Na githubu mas aktualni verzi?
Ze tam ten listview upravenej nikde nevidim :\
už to tam je jsem to prdnul do třídy ListViewFixed
Nestačí tam jen nadefinovat tu třídu ListViewFixed a nechat ji tam
ležet, musíš ji taky použít - ten tvuj seznam serverů musí bejt typu
ListViewFixed a ne ListView
Dík, zdá se že už to nebliká. Pomohl bys mi ještě s tím jak změnit obrázek pomocí toho tcp připojení? :[
Jestli to dobře chápu, tak ten obrázek kreslíš v metodě DrawItem.
Vlastně si všechny ty věci můžeš napsat do ListViewFixed - tam bych si
udělal třeba Dictionary stavů serverů a ten akorát v tý metodě DrawItem
pak podle toho vykreslíš.
Když nějakej server odeber, tak ho taky odebereš, když ho přidá, tak ho
přidáš a stav zatím třeba nastavíš na "zjišťuji".
A pak jen v té metodě DrawItem vykreslíš obrázek podle odpovídajícího záznamu v té kolekci.
Když spouštíš v novém vlákně nějakou tu metodu, co zjišťuje dostupnost, tak jí jen ještě předáš jako další parametr tu kolekci stavů a jen změníš stav toho jednoho serveru v té kolekci, až ho budeš vědět.
Nezapomeň to čtení/zapisování do té kolekce hodit do locku.
dostal jsem nápad a vyřešil jsem to tak že jsem jen načítal soubory...kde bude uložený počet MS a podle toho vykreslí obrázky...
private void ServerList_DrawItem(object sender, DrawListViewItemEventArgs e)
{
Bitmap MyIcon = global::Soulwell___Realmlist_modifer.Properties.Resources.off;
if (e.Item.Selected == true)
{
ServerList.ForeColor = Color.FromArgb(50, 146, 242); // blue text color
SolidBrush ItemColor = new SolidBrush(Color.FromArgb(51, 51, 51)); // gray ( 51, 51, 51) background color
Color BorderColor = Color.FromArgb(51, 102, 153); // blue ( 51, 102, 153 ) border color
e.Graphics.FillRectangle(ItemColor, e.Bounds.X, e.Bounds.Y, (float)210, e.Bounds.Height - 1); // active border
e.Graphics.DrawRectangle(new Pen(BorderColor), e.Bounds.X, e.Bounds.Y, (float)209, e.Bounds.Height - 1); // normal border
e.DrawText();
}
else
e.DrawText();
fl.LoadMyFile(ServersDir + e.Item.Text + Suffix, out Help[4]);
string[] rozdel = Help[4].Split(';');
if (rozdel[5] != "0")
{
mss.Text = rozdel[5];
MyIcon = global::Soulwell___Realmlist_modifer.Properties.Resources.on;
}
else
mss.Text = "0 ms";
e.Graphics.DrawImage(MyIcon, e.Bounds.Left + 190, e.Bounds.Top + 8, 10, 10);
MyIcon.Dispose();
//e.Graphics.DrawString(status, e.Item.Font, textColor, e.Bounds.Left + 2 + 40, e.Bounds.Top + 1);
}
A teď jsem v TCP upravím že až se to vykoná zapíše to počet MS do
souboru kde to bude drawitem číst myslím že docela dobrý nápad a moc díky za pomoc.
Uh, proc tak slozite, proc to zapisujes do souboru?
Jen si to uloz do nejakyho seznamu, kterej pri vykresleni prectes..
I kdyby sis mel treba udelat u ListViewFixed staticky List, tak je to porad
lepsi nez soubor
když ono chvíli trvá než to ten TCP zjistí a tak dlouho čekat nemůžu
už to někde musí být a
příležitostně když budu potřebovat si to aktualizuju :[
Jaký čekání pořád, vždyť to zjišťování, jestli se tcp připojí
děláš v jiným vlákně, tak ti aplikace nijak nezamrzne
A hlavně při každým překreslení načítat data ze souboru je
nehorázná prasárna
Popiš mi, který čekání přesně máš na mysli
čekání na to vlákno... jestli bude true nebo false xD a pac to bude
projizdet prázdný pole
každopádně teď už to pinguje a funguje jak má
já bych to nazval úspěšnou
prasárnou
A mit tam ze zacatku par milisekund (prinejhorsim i sekund) stav "zjistuje
se" by neslo?
šlo ale ty servery jsou udělaný dynamicky takže bych si to pole musel různě roztahovat a mazat aby tam byl pořád ten aktuální počet mě teda tohle příjde jako dobrý řešení ( těch serverů nebude milion aby to nějakým způsobem ohrozilo chod aplikace )
A přidat si teda tu hodnotu k serverům by nešlo?
já vím jak to myslíš no
důležitý je, že už to funguje
teď je podle mě jedno jestli to je přes pole nebo přes soubory
takže až teď fixnu případné chybky můžu samozřejmě předělat
No, předávat si hodnotu souborem, když si ji můžeš předávat uvnitř
programu mi příjde jako větší prasárna, než třeba použití příkazu
goto
jj to máš recht, pak to předělám důležitý je že to funguje prozatím
každopádně potřeboval
bych vědět poslední věc
kdybys mě navedl správným směrem byl bych ti vděčný
když kliknu mimo item (text) tak
nemám vlastně selectnuto nic, potřeboval bych to nějak udělat aby mi to
jako item(text) bralo celý řádek a ne jenom text... nevíš jak na to?
Nějakou mě neznámou metodičku?
Asi jsi už poznal že drawitem používám poprvé :[ předem díky
za radu
Zobrazeno 26 zpráv z 26.