[Win32/VB6] SystemParametersInfo probleem *

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Lorn
  • Registratie: Maart 2000
  • Laatst online: 13-01 11:03

Lorn

I have a bad feeling...

Topicstarter
Ik heb het volgende probleem:

Mijn applicatie krijgt een bericht binnen en moet op dat moment dwingend op de voorgrond komen. Opzich geen probleem ware het niet dat MS heeft besloten dit te blokeren van W98. Wat er gebeurd is dat applicatie in de taakbalk staat te knipperen voor aandacht maar het form word niet op de voorgrond getoond.

Omgeving:
- Windows 2000 Professional (SP4)
- Windows XP Professionel (SP1)
- Visual Basic 6 (SP5)

In mijn speurtocht door de MS Platform SDK kwam ik de routine SetForegroundWindow tegen met een heel stuk uitleg over hoe het te omzeilen doormiddel van het aanroepen van SystemParametersInfo met de parameter SPI_SETFOREGROUNDLOCKTIMEOUT. Meteen geprobeerd om dit te implementeren in VB6.

Uiteindelijk uitgekomen op deze code om de functionaliteit te testen:
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Private Declare Function SystemParametersInfo Lib "user32" _
   Alias "SystemParametersInfoA" _
  (ByVal uAction As Long, _
   ByVal uParam As Long, _
   ByRef lpvParam As Any, _
   ByVal fuWinIni As Long) As Long

Private Const SPI_GETFOREGROUNDLOCKTIMEOUT As Long = &H2000
Private Const SPI_SETFOREGROUNDLOCKTIMEOUT As Long = &H2001
Private Const SPIF_UPDATEINIFILE           As Long = &H1
Private Const SPIF_SENDWININICHANGE        As Long = &H2

Private Sub SetLockTimeout
  Dim lngFResult As Long
  Dim TimeOut    As Double

  TimeOut = CDbl(Text1.Text)
  lngFResult = SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0&, TimeOut, 0)
  MsgBox "lngFResult=" & CStr(lngFResult)
End Sub

Als ik nou probeer de timeout te zetten op 10ms dan maakt deze routine er 1242376ms van. Ik heb allerlei dingen geprobeerd (2de ipv 3de parameter gebruiken, meegeven als een VarPtr, etc.) maar niks hielp.

Na wat gezocht te hebben in diverse nieuwsgroepen een post tegen gekomen van Peter Below (TeamB member) met een voorbeeld voor Delphi. Dit heb ik geprobeerd in D7 maar had helaas hetzelfde resultaat als mijn VB applicatie. Ik heb mijn Delphi code zo niet bij de hand maar indien gewenst zal ik deze op een later tijdstip posten.

Er zijn twee dingen waar het volgens mij aan kan liggen maar ik kom er niet uit.
1) Ik geef mijn gewenste waarde voor de timeout verkeerd door. In de MS Platform SDK is niks te vinden over het datatype dat je moet gebruiken om de waarde door te geven.

2) Er staat in de SDK een opmerking bij de SPI_SETFORE... parameter: "The calling thread must be able to change the foreground window, otherwise the call will fail.". Nou weet ik niet zeker of mijn applicatie die rechten heeft en ik weet ook niet hoe dit uit te vragen. Feit is wel dat de aanroep van de API-call de waarde 1 terug geeft wat volgens de SDK aangeeft dat de call succesvol is gedaan.

Heeft er iemand een idee waar ik moet kijken om dit probleem op te lossen? Ik kom er namelijk echt niet meer uit. Vast al bedankt iig!

Acties:
  • 0 Henk 'm!

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 22-07 01:20

curry684

left part of the evil twins

Verander die double eens in een Long.

Professionele website nodig?


Acties:
  • 0 Henk 'm!

  • Lorn
  • Registratie: Maart 2000
  • Laatst online: 13-01 11:03

Lorn

I have a bad feeling...

Topicstarter
OK, heb de Double veranderd naar een Long. Helaas maakt dit niks uit (ben geloof ik zelfs begonnen met Long voor er een Double van gemaakt te hebben). Ik blijf waardes houden van rond de 1245xxx.

Acties:
  • 0 Henk 'm!

  • Lorn
  • Registratie: Maart 2000
  • Laatst online: 13-01 11:03

Lorn

I have a bad feeling...

Topicstarter
Voor als iemand het wil weten, dit is de code waarmee ik de waarde weer uitlees. Kan natuurlijk ook nog zijn dat daar een knoeperd van een fout inzit. Verwacht het alleen niet want zowel de VB als Delphi applicatie laten hetzelfde zien. Ook wanneer ik met TweakUI de waarde weer in zijn originele glorie herstel. TweakUI kan namelijk ook de instelling aanpassen (prevent stealing focus), helaas moet ik het echt vanuit de applicatie kunnen doen.

Visual Basic:
1
2
3
4
5
6
7
Private Sub GetTimeOut_Click()
  Dim lngResult  As Long
  Dim lngFResult As Long
  
  lngFResult = SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0&, lngResult, 0&)
  Label2.Caption = "Huidige setting: " & CStr(lngResult)
End Sub


Ik ga er vanuit dat deze code klopt. De initieele waarde is dan namelijk 200.000, bij elk ander type komen er alleen maar merkwaardige getallen uit.

[ Voor 12% gewijzigd door Lorn op 03-11-2003 16:56 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-07 03:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het moet iig een Long zijn, aangezien SETFOREGROUNDLOCKTIMEOUT een pointer naar DWORD verwacht. En werkt dat Any wel naar behoren? Stuurt VB dan geen type informatie mee ofzoiets? Maak van die declaratie ook eens een ByRef lpvParam As Long

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Lorn
  • Registratie: Maart 2000
  • Laatst online: 13-01 11:03

Lorn

I have a bad feeling...

Topicstarter
OK, alles aangepast naar Long.

De declaratie van SystemParametersInfo is zoals deze door de API Viewer van Visual Studio wordt opgegeven. Het veranderen van Any naar Long maakt niks uit, dit levert (helaas) nog steeds hetzelfde resultaat op.

Acties:
  • 0 Henk 'm!

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 22-07 01:20

curry684

left part of the evil twins

Mijn VB is brakjes maar ik betwijfel of je huidige syntax wel het adres van variabele TimeOut meegeeft, ik gok dat ie de waarde als adres gebruikt (wat idd een poep-getal op zal leveren).

Professionele website nodig?


Acties:
  • 0 Henk 'm!

  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 23-07 08:44

johnwoo

3S-GTE

Bij SPI_GETFOREGROUNDLOCKTIMEOUT dien je een pointer naar de variabele te geven waar de timeout waarde in wordt geschreven (ByRef). Bij SPI_SETFOREGROUNDLOCKTIMEOUT dien je echter direct de waarde zelf mee te geven, niet een pointer ernaar (ByVal). Hier zit je fout.

Omdat je sowieso iets ByVal moet meegeven kun je niet ByRef declareren. Je zal sowieso ByVal moeten nemen. Daarmee werkt SETFOREGROUNDLOCKTIMEOUT al meteen goed. Voor GETFOREGROUNDLOCKTIMEOUT kun je de pointer meegeven mbv VarPtr. Je krijgt dus zoiets (met een txtTimeout, een cmdSet en een cmdGet):

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Option Explicit

Private Declare Function SystemParametersInfo Lib "user32" _
    Alias "SystemParametersInfoA" _
    (ByVal uAction As Long, _
    ByVal uParam As Long, _
    ByVal lpvParam As Long, _
    ByVal fuWinIni As Long) As Long

Private Const SPI_GETFOREGROUNDLOCKTIMEOUT As Long = &H2000
Private Const SPI_SETFOREGROUNDLOCKTIMEOUT As Long = &H2001

Private Sub cmdGet_Click()
    Dim Timeout As Long, Result As Long
    
    Result = SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, _
        VarPtr(Timeout), 0)
    txtTimeout.Text = CStr(Timeout)

    Debug.Print "SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT)" & _
        " returned " & CStr(Result)
End Sub

Private Sub cmdSet_Click()
    Dim Timeout As Long, Result As Long
    
    Timeout = CLng(txtTimeout.Text)
    Result = SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, _
        Timeout, 0)

    Debug.Print "SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT)" & _
        " returned " & CStr(Result)
End Sub

[ Voor 24% gewijzigd door johnwoo op 04-11-2003 00:48 ]

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


Acties:
  • 0 Henk 'm!

  • Lorn
  • Registratie: Maart 2000
  • Laatst online: 13-01 11:03

Lorn

I have a bad feeling...

Topicstarter
johnwoo schreef op 04 november 2003 @ 00:43:
Bij SPI_GETFOREGROUNDLOCKTIMEOUT dien je een pointer naar de variabele te geven waar de timeout waarde in wordt geschreven (ByRef). Bij SPI_SETFOREGROUNDLOCKTIMEOUT dien je echter direct de waarde zelf mee te geven, niet een pointer ernaar (ByVal). Hier zit je fout.

Omdat je sowieso iets ByVal moet meegeven kun je niet ByRef declareren. Je zal sowieso ByVal moeten nemen. Daarmee werkt SETFOREGROUNDLOCKTIMEOUT al meteen goed. Voor GETFOREGROUNDLOCKTIMEOUT kun je de pointer meegeven mbv VarPtr. Je krijgt dus zoiets (met een txtTimeout, een cmdSet en een cmdGet):
_/-\o_ Helemaal geweldig! Dit is dus inderdaad de oplossing. Ik zou er zelf nooit uitgekomen zijn ben ik bang. Echt ontzettend bedankt! _/-\o_
Pagina: 1