глюки скринсейвера

Тема в разделе "WASM.WIN32", создана пользователем seiko, 26 ноя 2007.

  1. seiko

    seiko New Member

    Публикаций:
    0
    Регистрация:
    9 ноя 2007
    Сообщения:
    98
    Вот со скринсейвером косяк - прога рисует шарики заданных размеров и цветов поверх рабочего стола, делая его копию и переходя в графический режим, но возникла проблема
    она то работает то нет
    Иногда возникает уже надоевшая ошибка Canvas does not alow drawning иногда просто прога переходит в графический режим но ничё не рисует иногда нормально работает
    В чём косяк, может я не так чё-то уничтожаю перед закрытием?

    Вот код
    Главное в нём процедура Jeans

    Код (Text):
    1. unit jeansform;
    2.  
    3. interface
    4.  
    5. uses
    6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    7.   Dialogs, ExtCtrls, settings{модуль окна настроек}, registry;
    8.  
    9. {$D SCRNSAVE Jeansed.dpr}
    10.  
    11. type
    12.  
    13.   TForm1 = class(TForm)
    14.     procedure FormKeyPress(Sender: TObject; var Key: Char);
    15.     procedure FormCreate(Sender: TObject);
    16.     procedure FormShow(Sender: TObject);
    17.   private
    18.    FParameter:TScreenJoke;
    19.     { Private declarations }
    20.   public
    21.     { Public declarations }
    22.   end;
    23.  
    24. var
    25.   Form1: TForm1;
    26.  
    27. implementation
    28.  
    29.  
    30.  
    31. const
    32. colors:Array [0..21] of TColor=
    33. (clBlack,clMaroon,clGreen,clOlive,clNavy,clPurple,clTeal,clGray,
    34. clSilver,clRed,clLime,clYellow,clBlue,clFuchsia,clAqua,clLTGray,
    35. clDKGray,clWhite,clMoneyGreen,clSkyBlue,clCream,clMedGray);
    36.  
    37. Var DC,DC1:hdc; SX,SY,ID:cardinal;
    38.    h:integer; bit:TBitmap; d:Tcanvas;
    39.  
    40. Procedure InitializeKey(p:pointer);
    41. Var reg:TRegIniFile;
    42. Begin
    43. reg:=TRegIniFile.Create('Software');
    44. If reg.KeyExists('Jeans') then
    45.  with TScreenJoke(p^) do
    46.   begin
    47.    AllColors:=reg.ReadBool('Jeans','Colors',true);
    48.    OneSize:=reg.ReadBool('Jeans','OneSize',false);
    49.    invers:=reg.ReadBool('Jeans','Inversion',false);
    50.    If not AllColors then ParticularColor:=reg.ReadInteger('Jeans','PartColor',clRed)
    51.    else ParticularColor:=clNone;
    52.    LimitOfSize:=reg.ReadInteger('Jeans','Size',140);
    53.    Wait:=reg.ReadInteger('Jeans','WaitTime',50);
    54.   end
    55. else
    56. begin
    57.  reg.WriteBool('Jeans','Colors',true);
    58.  reg.WriteBool('Jeans','OneSize',false);
    59.  reg.WriteBool('Jeans','Inversion',false);
    60.  reg.WriteInteger('Jeans','PartColor',clNone);
    61.  reg.WriteInteger('Jeans','Size',140);
    62.  reg.WriteInteger('Jeans','WaitTime',50);
    63.  with TScreenJoke(p^) do
    64.   begin
    65.    AllColors:=true;
    66.    OneSize:=false;
    67.    ParticularColor:=clNone;
    68.    LimitOfSize:=140;
    69.    Wait:=50;
    70.   end;
    71. end;
    72. reg.Free;
    73. end;
    74.  
    75. procedure SetSettings(p:pointer);
    76. var reg:TRegIniFile;
    77. begin
    78. reg:=TRegIniFile.Create('Software');
    79. with TScreenJoke(p^) do
    80.   begin
    81.    reg.WriteBool('Jeans','Colors',AllColors);
    82.    reg.WriteBool('Jeans','OneSize',OneSize);
    83.    reg.WriteBool('Jeans','Inversion',invers);
    84.    reg.WriteInteger('Jeans','PartColor',ParticularColor);
    85.    reg.WriteInteger('Jeans','Size',LimitOfSize);
    86.    reg.WriteInteger('Jeans','WaitTime',Wait);
    87.   end;
    88. reg.Free;
    89. end;
    90.  
    91. Function Compare(x,y:PScreenJoke):boolean;
    92. Begin
    93. result:=(x^.AllColors=y^.AllColors) and (x^.oneSize=y^.oneSize)
    94. and (x^.ParticularColor=y^.ParticularColor) and (x^.invers=y^.invers)
    95. and (x^.LimitOfSize=y^.LimitOfSize) and (x^.Wait=y^.Wait);
    96. End;
    97.  
    98. {$R *.dfm}
    99.  
    100.  
    101. procedure Jeans(struct:pointer);
    102. Var Ifcol,inv:boolean; {r:TRect;} cons:cardinal;
    103. X, Y: Integer; size,sizelimit,time:cardinal; col:TColor;
    104. begin
    105. randomize;
    106. with PScreenJoke(struct)^ do
    107. begin
    108.  Ifcol:=AllColors;
    109.  sizelimit:=LimitOfSize+1;
    110.  if OneSize then size:=sizelimit;
    111.  inv:=invers;
    112.  if not ifcol then col:=ParticularColor;
    113.  time:=Wait;
    114. end;
    115. Form1.Left:=0;
    116. Form1.Top:=0;
    117. bit:=TBitmap.Create;
    118. SX:=GetSystemMetrics(0);
    119. SY:=GetSystemMetrics(1);
    120. bit.Width:=SX;
    121. bit.Height:=SY;
    122. DC:=GetDC(GetDesktopWindow);
    123. d:=TCanvas.Create;
    124. if inv then cons:=SRCInvert
    125. else cons:=SRCCopy;
    126. DC1:=GetDc(0);
    127. if not BitBlt(bit.Canvas.Handle,0,0,SX,SY,DC,0,0,cons) then
    128. begin
    129. MessageBox(0,'Drawning in this way is not allowed','Error',MB_ICONERROR);
    130. terminateprocess(GetCurrentProcess,0);
    131. end;
    132. d.Handle:=DC1;
    133. if not ifcol then
    134.  bit.Canvas.Brush.Color:=col;
    135. repeat
    136.  X := Random (SX);
    137.  Y := Random (SY);
    138.  if size<>sizelimit then size:=Random(sizelimit);
    139.  if ifcol then
    140.   bit.Canvas.Brush.Color:=colors[random(22)];
    141.  bit.Canvas.Ellipse(X - size, Y - size,
    142.  X + size, Y + size);
    143.  d.Draw(0,0,bit); ///Здесь раньше вылезала эта ошибка
    144.  sleep(time);
    145.  
    146. until false;
    147. end;
    148.  
    149.  
    150.  
    151.  
    152. procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
    153. begin
    154. terminatethread(h,0);
    155. d.Free;
    156. bit.Free;
    157. ReleaseDC(Form1.Handle,DC1);
    158. {ReleaseDc(Form1.Handle,DC); }
    159. UpdateWindow(GetDesktopWindow);
    160. Close;
    161. end;
    162.  
    163. procedure TForm1.FormCreate(Sender: TObject);
    164. begin
    165. InitializeKey(@FParameter);
    166. Data:=FParameter; ///Data - глобальная переменная модуля настроек
    167. end;
    168.  
    169. procedure TForm1.FormShow(Sender: TObject);
    170. begin
    171. if ParamCount>0 then
    172.   case paramStr(1)[2] of
    173.   'p':close;
    174.   'c':
    175.     begin
    176.      case Config.ShowModal of ///форма из модуля settings
    177.      mrOk:if not compare(@FParameter,@Data) then
    178.       begin
    179.        Fparameter:=Data;
    180.        SetSettings(@Fparameter);
    181.       end;
    182.      mrCancel:
    183.      end;
    184.      Close;
    185.     end;
    186.   end
    187. else
    188.  begin
    189.   Width:=SX;
    190.   Height:=SY;
    191.   h:=beginthread(nil,1024,@Jeans,@FParameter,0,ID);
    192.   ///CreateScreenSaverThread
    193.  end;
    194.  
    195.  
    196.  end;
    197.  
    198. end.
     
  2. seiko

    seiko New Member

    Публикаций:
    0
    Регистрация:
    9 ноя 2007
    Сообщения:
    98
    Вот код процедуры рисования
    Код (Text):
    1. procedure Jeans(struct:pointer);
    2. Var Ifcol,inv:boolean; {r:TRect;} cons:cardinal;
    3. X, Y: Integer; size,sizelimit,time:cardinal; col:TColor;
    4. begin
    5. randomize;
    6. with PScreenJoke(struct)^ do
    7. begin
    8.  Ifcol:=AllColors;
    9.  sizelimit:=LimitOfSize+1;
    10.  if OneSize then size:=sizelimit;
    11.  inv:=invers;
    12.  if not ifcol then col:=ParticularColor;
    13.  time:=Wait;
    14. end;
    15. Form1.Left:=0;
    16. Form1.Top:=0;
    17. bit:=TBitmap.Create;
    18. SX:=GetSystemMetrics(0);
    19. SY:=GetSystemMetrics(1);
    20. bit.Width:=SX;
    21. bit.Height:=SY;
    22. DC:=GetDC(GetDesktopWindow);
    23. d:=TCanvas.Create;
    24. if inv then cons:=SRCInvert
    25. else cons:=SRCCopy;
    26. DC1:=GetDc(0);
    27. if not BitBlt(bit.Canvas.Handle,0,0,SX,SY,DC,0,0,cons) then ///Вот здесь бывают проблемы с доступом
    28. begin
    29. MessageBox(0,'Drawning in this way is not allowed','Error',MB_ICONERROR);
    30. terminateprocess(GetCurrentProcess,0);
    31. end;
    32. d.Handle:=DC1;
    33. if not ifcol then
    34.  bit.Canvas.Brush.Color:=col;
    35. repeat
    36.  X := Random (SX);
    37.  Y := Random (SY);
    38.  if size<>sizelimit then size:=Random(sizelimit);
    39.  if ifcol then
    40.   bit.Canvas.Brush.Color:=colors[random(22)];
    41.  bit.Canvas.Ellipse(X - size, Y - size,
    42.  X + size, Y + size);
    43.  d.Draw(0,0,bit); ///Здесь чаще вылезала ошибка 'Canvas does not allow drawning'
    44.  sleep(time);
    45.  
    46. until false;
    47. end;
    Хочу заметить, что в большинстве случаев никаких ошибок не происходит просто ничё в графическом режиме не рисуется, и вместо копии рабочего стола стоит только фон графического режима
    Каковы предложения?
     
  3. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    seiko
    попробуй
    Код (Text):
    1. ...
    2. //d:=TCanvas.Create;
    3. ...
    4. //DC1:=GetDc(0);
    5. ...
    6. //d.Handle:=DC1;
    7. ...
    8. //d.Draw(0,0,bit); ///Здесь чаще вылезала ошибка 'Canvas does not allow drawning'
    9. BitBlt(DC, 0, 0, SX, SY, bit.Canvas.Handle, 0, 0, cons);
    10. ...
    + где-то _должно_ быть вызвано ReleaseDC(GetDesktopWindow, DC);
     
  4. seiko

    seiko New Member

    Публикаций:
    0
    Регистрация:
    9 ноя 2007
    Сообщения:
    98
    BitBlt(DC, 0, 0, SX, SY, bit.Canvas.Handle, 0, 0, cons);
    Этот код наоборот зачем, чтобы отображать изменения на реальном рабочем столе, а не а бутафории? Если да, так мне это не нужно, можно это гораздо проще сделать
    Если нет, это надо делать в цикле или по нажатию кнопки?

    с releaseDC тоже не работает, я уже проверял
    лишь дельфа от постоянных запусков так подвисает что её диспетчер завершить не может, и всё время система отчитывается об её убиении, хотя окно и проц остаются невредимыми
    В итоге либо перезагружать комп, либо пытаться убить PMasterом от MS_REMa или просто надеяться на чудо, которое, если быть терпеливым - происходит

    От чего такие глюки?
     
  5. CnCVK

    CnCVK New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2006
    Сообщения:
    108
    у программистов в Borland кривые руки....

    попробуй заключи код в try блок - может сообщение не будет вылазить (если это exception).

    посмотри в исходниках VCL - они идут в комплекте - сделай поиск по этой строке.
     
  6. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    seiko
    Этот код наоборот зачем ... так мне это не нужно
    Тогда поясни, что ты пытаешься сделать строчками
    Код (Text):
    1. ...
    2. d:=TCanvas.Create;
    3. ...
    4. DC1:=GetDc(0);
    5. // это аналог GetDC(GetDesktopWindow);
    6. // зачем тебе два контекста рабочего стола?
    7. ...
    8. d.Handle:=DC1;
    9. ...
    10. d.Draw(0,0,bit); ///Здесь чаще вылезала ошибка 'Canvas does not allow drawning'
    11. ...
    с releaseDC тоже не работает
    Не вижу в твоем коде ни одного ReleaseDC.
    GetDC и ReleaseDC это как begin и end в Pascal'е ходят парами.
     
  7. seiko

    seiko New Member

    Публикаций:
    0
    Регистрация:
    9 ноя 2007
    Сообщения:
    98
    в этом коде не было это просто старая редакция, а c ReleaseDC я пробовал уже

    объсни разницу между GetDC и GetWindowDC, а то я не шарю в чем фишка,
    если GetDC(0) - это тоже самое, что и GetWindowDC(GetDesktopWindow), то тогда что мы получим вызвав GetDc(GetDesktopWindow);

    попробовал присвоить Canvasу d DC(0) после bitBlt, процент нормально работающих разов увеличился
     
  8. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    seiko
    это просто старая редакция
    :dntknw: Зачем тогда его показывать?

    объсни разницу между GetDC и GetWindowDC
    Первая возвращает контекст клиентской области окна, дескриптор которого указан в качестве параметра. Вторая возвращает контекст всего окна, т.е. включая заголовок, рамку и.д.

    если GetDC(0) - это тоже самое, что и GetWindowDC(GetDesktopWindow), то тогда что мы получим вызвав GetDc(GetDesktopWindow);
    Логически - одно и тоже, т.к. у десктопа все окно - это клиентская часть, то разницы между GetDC и GetWindowDC нет. Что касается практики, то я ни разу не пытался получить одновременно несколько контекстов для одного окна. Afaik это ненормально.

    попробовал присвоить Canvasу d DC(0) после bitBlt
    Ты не ответил на вопрос: "Зачем это нужно?"
     
  9. seiko

    seiko New Member

    Публикаций:
    0
    Регистрация:
    9 ноя 2007
    Сообщения:
    98
    короче нашёл кусок проблемы
    вначале он рисует нормально
    почему-то
    canvas.Draw всё время работает по-разному,
    то он нормально рисует, то начинает рисовать, а потом убирает изображение и ставит фон формы,
    судя по всему первые несколько вызовов Draw проходят нормально глюки идут потом
    в самой поцедуре происходят вызовы SetBkColor(передается Brush.color) и SetTextColor(передается Font.Color)
    в итоге потом всё это покрываеться этим фоном вместо нарисованого в битмепе