Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > непонятный глюк с PROGRESS_CLASS


Автор: lollollollol 16.8.2013, 16:27
Здравствуйте.

Код

  {Создаю прогресс бар}
  PrgBar := CreateWindowEx(WS_EX_CLIENTEDGE,PROGRESS_CLASS, '', WS_CHILD, 100, 122, 235, 21, MainWnd, 0, hInstance, nil );
  SendMessage(PrgBar, PBM_SETRANGE,0, MAKELONG(0,100));
  SendMessage(PrgBar, PBM_SETSTEP, 1, 0);
  ShowWindow(PrgBar, SW_SHOWNORMAL);
  UpdateWindow(PrgBar);
  InitCommonControls();
//Потом выполняется ряд действий, передвигаю позицию так
SendMessage(PrgBar, PBM_SETPOS, 55, MAKELONG(0,100));


Но уже через минуту работы такой программы виснет весь комп, все окна дико тормозят, так, будьто видео карта не успевает обработать изменения.

Если закоментировать строку 
Код

  PrgBar := CreateWindowEx(WS_EX_CLIENTEDGE,PROGRESS_CLASS, '', WS_CHILD, 100, 122, 235, 21, MainWnd, 0, hInstance, nil );

То проблем нет. 

Как програсс бар может влиять на всю систему? Если он есть, тормозят ВСЕ окна. Я уже третий день бьюсь, всё перепробывал. Моет быть есть альтернативные полосы прогресса?
Хотя главный вопрос, как сделать чтобы небыло тормозов с полосой

ОС:Win7


спасибо

Автор: Чучмек 16.8.2013, 17:53
Цитата(lollollollol @  16.8.2013,  16:27 Найти цитируемый пост)
Но уже через минуту работы такой программы 

А сколько раз, за это время, меняется позиция?

Автор: lollollollol 16.8.2013, 18:50
0,25,55,85,86,87,88,89,90,91,92,93,94,95,100

15 раз.

Виснуть всё начинает примерно чере минуту после всего этого, и с каждой минутой всё сильнее. Через минут 5 доходит до того что окна почти не перерисовываются, а клик на кнопку закрытия программы отрабатывает аж через минуту, и всё это на 4-х ядерном компе с 4 гигами ОЗУ.

Автор: Poseidon 16.8.2013, 19:07
Покажи больше кода. Не удивлюсь, если узнаю, что у тебя там окажется цикл и PrgBar создается на каждой итерации. 

Автор: lollollollol 16.8.2013, 19:11
PrgBar создаётся при запуске программы, вместе со всем другими окнами.
Если просто создан прогресс бар, не висне. Виснет после выполнения этого кода. 
Причём я проверял бряком, код выполняется полностью, зацикливаний нет


Код

//Процедура подключения к серверу 
procedure ConnectToServers_UP;
var
  bk,login,pass,str:string;
  recv_len  :integer;
  rec      : Trec;
  req      : Treq;
  addr      : sockaddr_in;
  sock      : integer;
  error,port: integer;
  ip        :string;
  a:integer;
  TimeOutSSS:integer;
begin
  bk:=EditText(Edit1);
  login:=EditText(Edit2);
  pass:=EditText(Edit3);
  SaveConfigFile(bk,login,pass);
  login:=md5(login);
  pass:=md5(pass);
  SetWindowLong(Edit1,GWL_STYLE,WS_DISABLED);
  SetWindowLong(Edit2,GWL_STYLE,WS_DISABLED);
  SetWindowLong(Edit3,GWL_STYLE,WS_DISABLED);
  ShowWindow(PrgBar,SW_SHOWNORMAL);
  Showwindow(Buttons1,SW_HIDE);
  {Подключаюсь к БК серверу}
  SendMessage(PrgBar, PBM_SETPOS, 0, MAKELONG(0,100));
  sleep(50);
  SendMessage(PrgBar, PBM_SETPOS, 25, MAKELONG(0,100));
  str:='Connecting to BC server...';
  SendMessage(Label4, WM_SetText, Length(str),integer(@str[1]));
  //Коннект
  sock := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock=INVALID_SOCKET) then begin
    exit;
  end;
  timeOutSSS:=1000;
  SetSockOpt(sock, SOL_SOCKET, SO_RCVTIMEO, @TimeOutSSS, SizeOf(TimeOutSSS));
  port:=0;
  if (pos(':',bk)<>0) then begin
    port:=strtoint(copy(bk,Pos(':',bk)+1,length(bk)));
    ip:=copy(bk,0,Pos(':',bk)-1);
  end;
  addr.sin_family := AF_INET;
  addr.sin_port   := htons(port);
  addr.sin_addr.S_addr := inet_addr(Pchar(ip));
  error := connect(sock, addr, sizeof(addr));
  if (error<>SOCKET_ERROR) then begin
    sleep(700);
  SendMessage(PrgBar, PBM_SETPOS, 55, MAKELONG(0,100));
    str:='Connecting...';
    SendMessage(Label4, WM_SetText, Length(str),integer(@str[1]));
    //отправка информации
    req.types:=2;
    Move(login[1],req.login,length(login));
    Move(pass[1],req.pass,length(pass));
    recv_len:=Send(sock,req,SizeOf(req),0);
    if (recv_len<>SOCKET_ERROR) then begin
      sleep(700);
  SendMessage(PrgBar, PBM_SETPOS, 85, MAKELONG(0,100));
      str:='Authorization...';
      SendMessage(Label4, WM_SetText, Length(str),integer(@str[1]));
      //Ответ на авторизацию
      a:=0;
      while (a<10) do begin
        recv_len:=recv(sock,rec,sizeof(rec),MSG_PEEK);
        if (recv_len=SizeOf(rec)) then Break;
        inc(a);
  SendMessage(PrgBar, PBM_SETPOS, 85+a, MAKELONG(0,100));
      end;
      recv_len:=recv(sock,rec,sizeof(rec),MSG_PEEK);
      if (recv_len=SizeOf(rec)) then begin
  SendMessage(PrgBar, PBM_SETPOS, 100, MAKELONG(0,100));
        GLOBAL_KEY:='';
        SetString(GLOBAL_KEY,PChar(Cardinal(@rec.key)),SizeOf(rec.key));
        sleep(1000);
        if ((rec.types=2)and(rec.error=1)and(length(GLOBAL_KEY)=32)) then begin
          str:='Open';
          SendMessage(Label4, WM_SetText, Length(str),integer(@str[1]));
          sleep(1000);
          WindowLogin:=true;
          str:=' ';
        end else begin
          str:='      Login or password is incorrect';
        end;
      end else begin
        str:=syserrormessage(WSAGetLastError);;
      end;
    end else begin
      str:='      Failed to connect to server';
    end;
  end else begin
    str:=syserrormessage(WSAGetLastError);
  end;
  Shutdown(sock, SD_BOTH);
  closesocket(sock);
  SendMessage(Label4, WM_SetText, Length(str),integer(@str[1]));
  SetWindowLong(Edit1,GWL_STYLE,WS_VISIBLE or WS_CHILD);
  SetWindowLong(Edit2,GWL_STYLE,WS_VISIBLE or WS_CHILD);
  SetWindowLong(Edit3,GWL_STYLE,WS_VISIBLE or WS_CHILD);
  Showwindow(PrgBar,SW_HIDE);
  Showwindow(Buttons1,SW_NORMAL);
  ShowWindow(MainWnd, SW_SHOWNORMAL);
  UpdateWindow(MainWnd);
end;

Автор: Чучмек 16.8.2013, 20:58
lollollollol, а зачем такая мешанина WinAPI и VCL ?

Автор: lollollollol 16.8.2013, 20:59
где тут vcl?
Edit1 это хендл созданого окна вин апи

Автор: Чучмек 16.8.2013, 21:12
Цитата(lollollollol @  16.8.2013,  20:59 Найти цитируемый пост)
где тут vcl?
Edit1 это хендл созданого окна вин апи

Сори, недоглядел.
Какие сообщения и как обрабатываешь?
Можешь слепить пример попроще (оставив только PrgBar) который будет  зависать? 

Автор: lollollollol 16.8.2013, 21:28
Код

{Обработка сообщений окна авторизации}
function WindowProcLogin(Wnd, Msg, WParam, LParam: Integer): Integer; stdcall;
var
  ThID,tid:cardinal;
begin
  Result:=0;
  if (Msg=WM_DESTROY) then begin
    PostQuitMessage(0);
    PT(GetCurrentProcessId);
    exit;
  end;
  if (Msg=WM_COMMAND) then begin
    if (WParam=BTN_1) then begin
      ThID:=BeginThread(nil,0,@ConnectToServers,nil,0,tid);
      CloseHandle(ThID);
    end;
  end;
  Result := DefWindowProc(Wnd, Msg, WParam, LParam); 
end;



Нифига понять не могу
Убрал из кода всё кроме работы с прогрессом
Код

procedure ConnectToServers_UP;
var
  a:integer;
begin
  Showwindow(Buttons1,SW_HIDE);
  ShowWindow(PrgBar,SW_SHOWNORMAL);
  SendMessage(PrgBar, PBM_SETPOS, 0, MAKELONG(0,100));
  sleep(50);
  SendMessage(PrgBar, PBM_SETPOS, 25, MAKELONG(0,100));
  SendMessage(PrgBar, PBM_SETPOS, 55, MAKELONG(0,100));
  sleep(700);
  SendMessage(PrgBar, PBM_SETPOS, 85, MAKELONG(0,100));
  a:=0;
  while (a<10) do begin
    sleep(500);
    inc(a);
    SendMessage(PrgBar, PBM_SETPOS, 85+a, MAKELONG(0,100));
  end;
  SendMessage(PrgBar, PBM_SETPOS, 100, MAKELONG(0,100));
  sleep(1000);
  Showwindow(PrgBar,SW_HIDE);
  ShowWindow(MainWnd, SW_SHOWNORMAL);
  UpdateWindow(MainWnd);
end;


Тормоза пропали. 


ВСё, щас буду головой биться!


Если не создавать окно прогресса , всё нормально, и если убрать всё лишнее, но оставить окно, тоже нормально, бред...

Добавлено через 6 минут и 54 секунды
Хотя ошибаюсь, Глюки ЕСТЬ! 
Просто они не в течении минуты, а в течении 3х минут проявились. прошло 5 минут, с трудом чтото могу сделать, всё тормозит

Автор: northener 16.8.2013, 22:33
А почему LPARAM у PBM_SETPOS не нулевой?

Автор: lollollollol 17.8.2013, 07:58
Вообщем испробывал всё что мог.
Если создавать прогресс бар непосредственно перед его использованием, а не при запуске программы, то нет красивой виндовской анимации.



РЕШЕНИЕ НАЙДЕНО. Незнаю на сколько корректное.
После отработки прогресс бара отправляю окну

Код

  SendMessage(PrgBar, WM_DESTROY,0, 0);
  SendMessage(PrgBar,WM_QUIT,0,0);
  SendMessage(PrgBar,WM_Close,0,0);
PrgBar:=0;

а в обработчике прописал так:
Код

  while (GetMessage(Msg, 0,0,0)=True) do begin
...
    if (PrgBar=0) then begin
      PrgBar:=CreateWindowEx(WS_EX_CLIENTEDGE,PROGRESS_CLASS, '', WS_CHILD, 100, 122, 235, 21, MainWnd, 0, hInstance, nil );
    end;

Таким образом у меня всегда свежее окно, глюк изчез.


Но в чём была причина до этого, непонятно. Я думаю это связан с виндовой анимацией прогресс бара



Спасибо всем, кто откликнулся!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)