[C#] Newbie vraagje

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Squ1zZy
  • Registratie: April 2011
  • Niet online
Ik ben al een uurtje aan het stoeien met wat code, maar kom er helaas niet uit. Ik heb de gekste dingen gedaan, maar gezien mijn minimale kennis kom ik er gewoonweg niet uit :(

Ik heb een sysTray applicatie gemaakt die items, aan de hand van MenuItems.Add, toevoegd.
code:
1
2
3
4
5
6
7
8
9
10
11
12
            foreach (Process process in processlist)
            {
                if (!String.IsNullOrEmpty(process.MainWindowTitle))
                {
                    sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop);
                }
            }

        private void onTop(object sender, EventArgs e)
        {
            Program.AlwaysOnTop("test");
        }


Dit werkt prima. Echter wil ik dat onTop wordt aangeroepen met als "process.MainWindowTitle" als parameter. Dus dat "test" wordt vervangen met MainWindowTitle. Ik mis alleen iets. Wie wil mij een zetje in de juiste richting geven?

Beste antwoord (via Squ1zZy op 14-01-2016 11:25)


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Squ1zZy schreef op woensdag 13 januari 2016 @ 16:45:
Ik ben al een uurtje aan het stoeien met wat code, maar kom er helaas niet uit. Ik heb de gekste dingen gedaan, maar gezien mijn minimale kennis kom ik er gewoonweg niet uit :(

Ik heb een sysTray applicatie gemaakt die items, aan de hand van MenuItems.Add, toevoegd.
code:
1
2
3
4
5
6
7
8
9
10
11
12
            foreach (Process process in processlist)
            {
                if (!String.IsNullOrEmpty(process.MainWindowTitle))
                {
                    sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop);
                }
            }

        private void onTop(object sender, EventArgs e)
        {
            Program.AlwaysOnTop("test");
        }


Dit werkt prima. Echter wil ik dat onTop wordt aangeroepen met als "process.MainWindowTitle" als parameter. Dus dat "test" wordt vervangen met MainWindowTitle. Ik mis alleen iets. Wie wil mij een zetje in de juiste richting geven?
Je wil dat de data van je process beschikbaar is in je event_handler. Aangezien die data alleen in de scope van je foreach loop beschikbaar is kun je er in je event_handler niet meer bij.

Daar zijn drie oplossingen voor:

1. Je maakt een class aan waar je die data instopt, en verplaatst de event handler naar die class
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        var processData = new ProcessData(process.MainWindowTitle);
        sysTrayMenu.MenuItems.Add(process.MainWindowTitle, processData.OnTop);
    }
}

public class ProcessData
{
    private string _title;

    public ProcessData(string title)
    {
        _title = title;
    }

    public void OnTop(object sender, EventArgs args)
    {
        Program.AlwaysOnTop(_title);
    }
}

2: Je gebruikt een lambda/anonyous delegate en maakt gebruikt van de "Closure" functionaliteit
C#:
1
2
3
4
5
6
7
8
9
10
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        sysTrayMenu.MenuItems.Add(process.MainWindowTitle, (sender, args) =>
        {
            Program.AlwaysOnTop(process.MainWindowTitle);
        });
    }
}


Wat YakuzA zegt is ook een optie, maar je wil niet perse dat je text van je MenuItem exact gelijk is aan de text die je mee wil geven. Je kan dan kiezen om de data in de Tag van je MenuItem te zetten.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        var menuItem = sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop);
        menuItem.Tag = process.MainWindowTitle;
    }
}

private void onTop(object sender, EventArgs e)
{
    var title = ((MenuItem) sender).Tag as string;
    if(title != null)
    {
        Program.AlwaysOnTop(title);
    }
}


Bovenstaande code zal waarschijnlijk niet exact compilen, want heb het uit de losse pols ingetypt, maar het gaat om het idee.

[ Voor 14% gewijzigd door Woy op 14-01-2016 09:42 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Alle reacties


Acties:
  • 0 Henk 'm!

  • supreme tweaker
  • Registratie: December 2002
  • Laatst online: 28-08 01:27
Je zal een eigen event definitie moeten maken waarbij de parameters van de handler delegate overeenkomen met de parameters die je verwacht.

Burp


Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
onTop is een methode, dus op z'n minst onTop()

Verder, als je iets als parameter wil meegeven moet het in de () zitten van de methode die je aanroept, dus onTop(process.MainWindowTitle)

Acties:
  • 0 Henk 'm!

  • Squ1zZy
  • Registratie: April 2011
  • Niet online
Chrotenise schreef op woensdag 13 januari 2016 @ 16:50:
onTop is een methode, dus op z'n minst onTop()

Verder, als je iets als parameter wil meegeven moet het in de () zitten van de methode die je aanroept, dus onTop(process.MainWindowTitle)
Dat dacht ik door dit te doen:

code:
1
2
3
4
5
6
sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop(process.MainWindowTitle.ToString()));

void onTop(string value)
{
    Program.AlwaysOnTop(value);
}

Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
Squ1zZy schreef op woensdag 13 januari 2016 @ 16:53:
[...]


Dat dacht ik door dit te doen:

code:
1
2
3
4
5
6
sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop(process.MainWindowTitle.ToString()));

void onTop(string value)
{
    Program.AlwaysOnTop(value);
}
!String.IsNullOrEmpty(process.MainWindowTitle)

proces.MainWindowTitle is dus al een string, dus .ToString() is dubbelop.

Wat gaat er verder fout als je dit doet?

Acties:
  • 0 Henk 'm!

  • Squ1zZy
  • Registratie: April 2011
  • Niet online
Chrotenise schreef op woensdag 13 januari 2016 @ 16:56:
[...]


!String.IsNullOrEmpty(process.MainWindowTitle)

proces.MainWindowTitle is dus al een string, dus .ToString() is dubbelop.

Wat gaat er verder fout als je dit doet?
Hier krijg ik een melding op:

onTop(process.MainWindowTitle));

Namelijk:

Argument 2: cannot convert from 'void' to 'System.EventHandler'

Acties:
  • 0 Henk 'm!

  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

Chrotenise schreef op woensdag 13 januari 2016 @ 16:50:
onTop is een methode, dus op z'n minst onTop()
De methode is hier het argument (een delegate) toch? Dan juist zonder haakjes, anders wordt hij aangeroepen en het resultaat daarvan is geen delegate maar void. En dan krijg je de foutmelding die Squ1zZy dus net krijgt.

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
Squ1zZy schreef op woensdag 13 januari 2016 @ 16:57:
[...]

Hier krijg ik een melding op:

onTop(process.MainWindowTitle));

Namelijk:

Argument 2: cannot convert from 'void' to 'System.EventHandler'
Had ik kunnen zien aankomen. Ik weet niet waarom je in een aparte methode de onTop wil doen, maar dit is efficiënter.

code:
1
2
3
4
5
6
7
8
9
10
using System.Linq;

onTop(processlist
    .First(a => !String.IsNullOrEmpty(a.MainWindowTitle))
    .MainWindowTitle);
    
private void onTop(string s)
{
    Program.AlwaysOnTop(s);
}


Indien je niet zeker weet dat processList een Process met MainWindowTitle zal bevatten:

code:
1
2
3
4
5
6
7
8
9
10
11
var process = processlist
    .FirstOrDefault(a => !String.IsNullOrEmpty(a.MainWindowTitle);

if (process != null)
{
     onTop(process.MainWindowTitle);
}
private void onTop(string s)
{
    Program.AlwaysOnTop(s);
}
kenneth schreef op woensdag 13 januari 2016 @ 17:05:
[...]
De methode is hier het argument (een delegate) toch? Dan juist zonder haakjes, anders wordt hij aangeroepen en het resultaat daarvan is geen delegate maar void. En dan krijg je de foutmelding die Squ1zZy dus net krijgt.
Delegates moeten eerst declared worden als zijnde een delegate. Zie:
MSDN: Using Delegates (C# Programming Guide)

Acties:
  • 0 Henk 'm!

  • Squ1zZy
  • Registratie: April 2011
  • Niet online
Chrotenise schreef op woensdag 13 januari 2016 @ 17:51:
[...]


Had ik kunnen zien aankomen. Ik weet niet waarom je in een aparte methode de onTop wil doen, maar dit is efficiënter.

code:
1
2
3
4
5
6
7
8
9
10
using System.Linq;

onTop(processlist
    .First(a => !String.IsNullOrEmpty(a.MainWindowTitle))
    .MainWindowTitle);
    
private void onTop(string s)
{
    Program.AlwaysOnTop(s);
}


Indien je niet zeker weet dat processList een Process met MainWindowTitle zal bevatten:

code:
1
2
3
4
5
6
7
8
9
10
11
var process = processlist
    .FirstOrDefault(a => !String.IsNullOrEmpty(a.MainWindowTitle);

if (process != null)
{
     onTop(process.MainWindowTitle);
}
private void onTop(string s)
{
    Program.AlwaysOnTop(s);
}



[...]


Delegates moeten eerst declared worden als zijnde een delegate. Zie:
MSDN: Using Delegates (C# Programming Guide)
Zo bedoel je?

sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop(processlist.First(a => !String.IsNullOrEmpty(a.MainWindowTitle)).MainWindowTitle);

Krijg steeds dezelfde melding :|

Acties:
  • 0 Henk 'm!

  • Chrotenise
  • Registratie: December 2011
  • Niet online
Nee, gewoon in een losse regel erboven.

code:
1
2
3
4
onTop(processlist.First(a => !String.IsNullOrEmpty(a.MainWindowTitle)).MainWindowTitle);

foreach(var process in processlist)
       sysTrayMenu.MenuItems.Add(process.MainWindowTitle);

Acties:
  • 0 Henk 'm!

  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

Chrotenise schreef op woensdag 13 januari 2016 @ 17:51:
Delegates moeten eerst declared worden als zijnde een delegate. Zie:
MSDN: Using Delegates (C# Programming Guide)
Eh? Dat is System.EventHandler toch :?

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


Acties:
  • 0 Henk 'm!

  • Squ1zZy
  • Registratie: April 2011
  • Niet online
Chrotenise schreef op woensdag 13 januari 2016 @ 19:52:
Nee, gewoon in een losse regel erboven.

code:
1
2
3
4
onTop(processlist.First(a => !String.IsNullOrEmpty(a.MainWindowTitle)).MainWindowTitle);

foreach(var process in processlist)
       sysTrayMenu.MenuItems.Add(process.MainWindowTitle);
Sorry, deze snap ik niet. Ik wil onTop aanroepen met 1 van de items die is toegevoegd aan de sysTray.
Nu wordt het eerste proces in de processlist aangeroepen en daarna worden de items toegevoegd?

Acties:
  • 0 Henk 'm!

  • YakuzA
  • Registratie: Maart 2001
  • Niet online

YakuzA

Wat denk je nou zelluf hey :X

Squ1zZy schreef op woensdag 13 januari 2016 @ 16:45:
Ik ben al een uurtje aan het stoeien met wat code, maar kom er helaas niet uit. Ik heb de gekste dingen gedaan, maar gezien mijn minimale kennis kom ik er gewoonweg niet uit :(

Ik heb een sysTray applicatie gemaakt die items, aan de hand van MenuItems.Add, toevoegd.
code:
1
2
3
4
5
6
7
8
9
10
11
12
            foreach (Process process in processlist)
            {
                if (!String.IsNullOrEmpty(process.MainWindowTitle))
                {
                    sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop);
                }
            }

        private void onTop(object sender, EventArgs e)
        {
            Program.AlwaysOnTop("test");
        }


Dit werkt prima. Echter wil ik dat onTop wordt aangeroepen met als "process.MainWindowTitle" als parameter. Dus dat "test" wordt vervangen met MainWindowTitle. Ik mis alleen iets. Wie wil mij een zetje in de juiste richting geven?
Het enige wat je hoeft te doen is je "object sender" wat je binnenkrijgt bij het event via de debugger te bekijken, daarna cast je die naar het goede type, en pak je de bijv. .Text property daarvan.

Misschienis je sender gewoon het MenuItem.
Dus dat zal lijken op bijv:
code:
1
Program.AlwaysOnTop(((MenuItem)sender).Text);

Death smiles at us all, all a man can do is smile back.
PSN


Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Squ1zZy schreef op woensdag 13 januari 2016 @ 16:45:
Ik ben al een uurtje aan het stoeien met wat code, maar kom er helaas niet uit. Ik heb de gekste dingen gedaan, maar gezien mijn minimale kennis kom ik er gewoonweg niet uit :(

Ik heb een sysTray applicatie gemaakt die items, aan de hand van MenuItems.Add, toevoegd.
code:
1
2
3
4
5
6
7
8
9
10
11
12
            foreach (Process process in processlist)
            {
                if (!String.IsNullOrEmpty(process.MainWindowTitle))
                {
                    sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop);
                }
            }

        private void onTop(object sender, EventArgs e)
        {
            Program.AlwaysOnTop("test");
        }


Dit werkt prima. Echter wil ik dat onTop wordt aangeroepen met als "process.MainWindowTitle" als parameter. Dus dat "test" wordt vervangen met MainWindowTitle. Ik mis alleen iets. Wie wil mij een zetje in de juiste richting geven?
Je wil dat de data van je process beschikbaar is in je event_handler. Aangezien die data alleen in de scope van je foreach loop beschikbaar is kun je er in je event_handler niet meer bij.

Daar zijn drie oplossingen voor:

1. Je maakt een class aan waar je die data instopt, en verplaatst de event handler naar die class
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        var processData = new ProcessData(process.MainWindowTitle);
        sysTrayMenu.MenuItems.Add(process.MainWindowTitle, processData.OnTop);
    }
}

public class ProcessData
{
    private string _title;

    public ProcessData(string title)
    {
        _title = title;
    }

    public void OnTop(object sender, EventArgs args)
    {
        Program.AlwaysOnTop(_title);
    }
}

2: Je gebruikt een lambda/anonyous delegate en maakt gebruikt van de "Closure" functionaliteit
C#:
1
2
3
4
5
6
7
8
9
10
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        sysTrayMenu.MenuItems.Add(process.MainWindowTitle, (sender, args) =>
        {
            Program.AlwaysOnTop(process.MainWindowTitle);
        });
    }
}


Wat YakuzA zegt is ook een optie, maar je wil niet perse dat je text van je MenuItem exact gelijk is aan de text die je mee wil geven. Je kan dan kiezen om de data in de Tag van je MenuItem te zetten.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        var menuItem = sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop);
        menuItem.Tag = process.MainWindowTitle;
    }
}

private void onTop(object sender, EventArgs e)
{
    var title = ((MenuItem) sender).Tag as string;
    if(title != null)
    {
        Program.AlwaysOnTop(title);
    }
}


Bovenstaande code zal waarschijnlijk niet exact compilen, want heb het uit de losse pols ingetypt, maar het gaat om het idee.

[ Voor 14% gewijzigd door Woy op 14-01-2016 09:42 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Squ1zZy
  • Registratie: April 2011
  • Niet online
Woy schreef op donderdag 14 januari 2016 @ 09:38:
[...]


Je wil dat de data van je process beschikbaar is in je event_handler. Aangezien die data alleen in de scope van je foreach loop beschikbaar is kun je er in je event_handler niet meer bij.

Daar zijn drie oplossingen voor:

1. Je maakt een class aan waar je die data instopt, en verplaatst de event handler naar die class
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        var processData = new ProcessData(process.MainWindowTitle);
        sysTrayMenu.MenuItems.Add(process.MainWindowTitle, processData.OnTop);
    }
}

public class ProcessData
{
    private string _title;

    public ProcessData(string title)
    {
        _title = title;
    }

    public void OnTop(object sender, EventArgs args)
    {
        Program.AlwaysOnTop(_title);
    }
}

2: Je gebruikt een lambda/anonyous delegate en maakt gebruikt van de "Closure" functionaliteit
C#:
1
2
3
4
5
6
7
8
9
10
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        sysTrayMenu.MenuItems.Add(process.MainWindowTitle, (sender, args) =>
        {
            Program.AlwaysOnTop(process.MainWindowTitle);
        });
    }
}


Wat YakuzA zegt is ook een optie, maar je wil niet perse dat je text van je MenuItem exact gelijk is aan de text die je mee wil geven. Je kan dan kiezen om de data in de Tag van je MenuItem te zetten.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
foreach (Process process in processlist)
{
    if (!String.IsNullOrEmpty(process.MainWindowTitle))
    {
        var menuItem = sysTrayMenu.MenuItems.Add(process.MainWindowTitle, onTop);
        menuItem.Tag = process.MainWindowTitle;
    }
}

private void onTop(object sender, EventArgs e)
{
    var title = ((MenuItem) sender).Tag as string;
    if(title != null)
    {
        Program.AlwaysOnTop(title);
    }
}


Bovenstaande code zal waarschijnlijk niet exact compilen, want heb het uit de losse pols ingetypt, maar het gaat om het idee.
Alles werkt :)

Super bedankt allemaal!


Het was even puzzelen en ik moet de oplossingen even opzoeken waarom dit wel werkt, maar de applicatie is af. Ik kan nu een applicatie always-on-top houden als de applicatie dat zelf niet ondersteunt.
Pagina: 1