Seite 1 von 1

WaitWindowEvent - Problemchen

Verfasst: 31.05.2006 15:14
von PBZecke
Hallo!

Ich habe folgenden Code hier im Forum gefunden und an PB 4 angepasst.
Es ist ein Download mit Progressbar. Interessant ist auch die Möglichkeit
den Download abzubrechen. Dafür hat der Autor die proc DoEvents()
eingebaut. Leider funktioniert das nicht!

Daher habe ich zusätzlich einen WindowCallback hinzugefügt, damit es
funktioniert. Meine Frage ist nun warum WaitWindowEvent nicht die Events
von DispatchMessage_() in DoEvents() erhält. #PB_Event_CloseWindow
wird zwar empfangen aber erst bei abgeschlossenem Download.
Gadget-Events gehen ohne Callback ganz verloren. Funktionierte das in
PB 3.94?

Zum Testen einfach mal SetWindowCallback(@WndPrc())
auskommentieren und den Button EXIT während des Downloads
anklicken.




Code: Alles auswählen

; English forum: http://purebasic.myforums.net/viewtopic.php?t=8331&highlight=
; Author: V2
; Date: 13. November 2003



Enumeration 
  #Window 
  #cmdStart 
  #progressbar 
  #Frame 
  #cmdExit 
  #Label 
  #Label2 
  #URL 
EndEnumeration 



Procedure WndPrc(WindowID, Message, wParam, lParam) 

  Protected result
  result = #PB_ProcessPureBasicEvents 
  
  If Message = #WM_COMMAND
     If wParam >> 16 = #BN_CLICKED 
        Select lParam 
           Case GadgetID(#cmdExit)
              End
           Case GadgetID(#cmdStart)
              ;do nothing here
        EndSelect
     EndIf
  EndIf
  
  If Message = #WM_CLOSE
     End
  EndIf
    
  ProcedureReturn result
  
EndProcedure 


;SetWindowCallback aukommentieren um Waitwindowevent() zu testen!
SetWindowCallback(@WndPrc()) 




Procedure.s Reverse(s.s) 
  O.s=Mid(s,Len(s),1) 
  P=Len(s)-1 
  While P>0 
    O.s=O+Mid(s,P,1) 
    P=P-1 
  Wend 
  ProcedureReturn O 
EndProcedure 


Procedure DoEvents() 
  msg.MSG 
  If PeekMessage_(msg,0,0,0,1) 
    TranslateMessage_(msg) 
    DispatchMessage_(msg) 
  Else 
    Sleep_(1) 
  EndIf 
EndProcedure 



Procedure.s GetQueryInfo(hHttpRequest.l, iInfoLevel.l) 
  lBufferLength.l=0 
  lBufferLength = 1024 
  sBuffer.s=Space(lBufferLength) 
  HttpQueryInfo_(hHttpRequest, iInfoLevel, sBuffer, @lBufferLength, 0) 
  ProcedureReturn Left(sBuffer, lBufferLength) 
EndProcedure 



Procedure UrlToFileWithProgress(myFile.s, URL.s) 
  isLoop.b=1 
  Bytes.l=0 
  fBytes.l=0 
  Buffer.l=4096 
  res.s="" 
  tmp.s="" 
  
  OpenType.b=1 
  #INTERNET_FLAG_RELOAD = $80000000 
  INTERNET_DEFAULT_HTTP_PORT.l = 80 
  INTERNET_SERVICE_HTTP.l = 3 
  HTTP_QUERY_STATUS_CODE.l = 19 
  HTTP_QUERY_STATUS_TEXT.l = 20 
  HTTP_QUERY_RAW_HEADERS.l = 21 
  HTTP_QUERY_RAW_HEADERS_CRLF.l = 22 

  mem=AllocateMemory(Buffer) 


  Result = CreateFile(1, myFile) 
  hInet = InternetOpen_("", OpenType, #Null, #Null, 0) 
  hURL = InternetOpenUrl_(hInet, URL, #Null, 0, #INTERNET_FLAG_RELOAD, 0) 
  
  ;get Filesize 
  domain.s = ReplaceString(Left(URL,(FindString(URL, "/",8) - 1)),"http://","") 
  hInetCon = InternetConnect_(hInet,domain, INTERNET_DEFAULT_HTTP_PORT, #Null, #Null, INTERNET_SERVICE_HTTP, 0, 0) 
  If hInetCon > 0 
    hHttpOpenRequest = HttpOpenRequest_(hInetCon, "HEAD", ReplaceString(URL,"http://"+domain+"/",""), "http/1.1", #Null, 0, INTERNET_FLAG_RELOAD, 0) 
    If hHttpOpenRequest > 0 
      iretval = HttpSendRequest_(hHttpOpenRequest, #Null, 0, 0, 0) 
      If iretval > 0 
        tmp = GetQueryInfo(hHttpOpenRequest, HTTP_QUERY_STATUS_CODE) 
        If Trim(tmp) = "200" 
          tmp = GetQueryInfo(hHttpOpenRequest, HTTP_QUERY_RAW_HEADERS_CRLF) 
          If FindString(tmp,"Content-Length:",1)>0 
            ii.l=FindString(tmp, "Content-Length:",1) + Len("Content-Length:") 
            tmp = Mid(tmp, ii, Len(tmp)-ii) 
            myMax = Val(Trim(tmp)) 
          EndIf 
        EndIf 
      EndIf 
    EndIf 
  EndIf 
  
  SetGadgetText(#Label, "Filesize: " + Str(myMax)) 
  SetGadgetAttribute(#progressbar, #PB_ProgressBar_Maximum, myMax) 
  
  ;start downloading 
  Repeat 
    InternetReadFile_(hURL, mem, Buffer, @Bytes) 
    If Bytes = 0 
      isLoop=0 
    Else 
      fBytes=fBytes+Bytes 
        SetGadgetText(#Label2, "Received Bytes: " + Str(fBytes)) 
      If myMax >= fBytes: SetGadgetState(#progressbar, fBytes): EndIf 
 
      WriteData(1,mem, Bytes) 
    EndIf 
      DoEvents() 
  Until isLoop=0 
  InternetCloseHandle_(hURL) 
  InternetCloseHandle_(hInet) 
  SetGadgetState(#progressbar, 0) 
  CloseFile(1)    
  FreeMemory(0) 
EndProcedure 



If OpenWindow(#Window, 0, 0, 400, 175, "Download with Progress", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered ) 

  If CreateGadgetList(WindowID(#Window)) 
      StringGadget(#URL, 10, 10, 380, 20, "http://www.largeformatphotography.info/qtluong/sequoias.big.jpeg") 
      ProgressBarGadget(#progressbar, 10, 40, 380, 30, 0,100 , #PB_ProgressBar_Smooth) 
      TextGadget(#Label, 10, 80,300,20,"Filesize:") 
      TextGadget(#Label2, 10, 100,300,20,"Bytes received:") 
      Frame3DGadget(#Frame, -10, 120, 420, 110, "") 
      ButtonGadget(#cmdExit, 160, 140, 110, 25, "Exit") 
      ButtonGadget(#cmdStart, 280, 140, 110, 25, "Start", #PB_Button_Default) 
      
  EndIf 
        
  Repeat 
    EventID.l = WaitWindowEvent() 
    If EventID = #PB_Event_Gadget    
      Select EventGadget() 
        Case #cmdStart 
        
          URL.s = GetGadgetText(#URL) 
          
          ;get filename (checking /) 
          myFile.s= Right(URL, FindString(Reverse(URL),"/",1)-1) 
          ;request path 
          myFolder.s = PathRequester ("Where do you want to save '" + myFile + "'?", "C:\") 

          UrlToFileWithProgress(myFolder + myFile, URL) 
        Case #cmdExit 
          End 
      EndSelect 
    EndIf               
  Until EventID = #PB_Event_CloseWindow 
EndIf 
End 

Verfasst: 31.05.2006 18:50
von real
Ziemlich einfach:
Das WaitWindowEvent() wird in der Repeat-Until-Schleife erst wieder aufgerufen, nachdem die Prozedur UrlToFileWithProgress() beendet ist. In der Prozedure selbst holt sich die DoEvents() Prozedure die Ereignisse per WindowCallback von Windows.

Ruf UrlToFileWithProgress() mal per CreateThread() auf und entfern den SetWindowCallback-Kram und DoEvents() - dann funktioniert's auch mit WaitWindowEvent().

Verfasst: 31.05.2006 19:10
von PBZecke
real hat geschrieben:Ziemlich einfach:
Das WaitWindowEvent() wird in der Repeat-Until-Schleife erst wieder aufgerufen, nachdem die Prozedur UrlToFileWithProgress() beendet ist.
Ja, habe ich inzwichen auch schon bemerkt. Aber das zeigt mir wie unflexiblel
WaitWindowEvent ist. In allen meinen PB-Programmen muss ich immer
wieder auf einen CallBack zurückgreifen. Thread ist hier unnötig,
meine Änderungen funktionieren ja...

Verfasst: 31.05.2006 19:43
von ts-soft
Ausser in recht einfachen Programmen, wirste immer Callbacks brauchen. Unter Linux kommst auch mit den einfachen WaitWindowEvents nicht immer klar. Alles was einfach ist, wird auch Einschränkungen haben.
Tip: Nutze EasyVENt.pbi, findeste im engl. Forum.

Verfasst: 31.05.2006 21:28
von PBZecke
Habs mir mal kurz angeschaut. Scheint gerade für größere Sachen sehr
geignet zu sein. Danke für den Tipp! :allright: