Rafraichissement TImage

Résolu
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 - 12 avril 2006 à 18:53
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 - 13 avril 2006 à 23:03
J'ai crée un petit programme qui résoud les Sudoku (je le posterais pas, il y en a déjà assez sur ce site).
J'utilise un TImage pour afficher la grille. Malheureusement, elle ne se rafraichît pas correctement (je suis obligé de faire passer une autre fenetre par dessus pour qu'il daigne m'afficher quelquechose). Soit il ne m'affiche rien, soit il m'affiche partiellement ce que je veux..

J'ai essayer plusieurs méthodes, comme le DoubleBuffered := True, le Repaint, le Refresh et j'ai meme essayer des API qui force le le rafraichaissement (WM_PAINT + un timer).

Rien à faire ca ne marche pas.
Ma source: http://0217021.free.fr/Cours/Sudoku.rar

Je remercie celui qui pourra m'aider.

7 réponses

Emandhal Messages postés 194 Date d'inscription dimanche 2 mars 2003 Statut Membre Dernière intervention 10 octobre 2006 3
13 avril 2006 à 13:27
Si tu veux ton jeu modifié de tout ce que je t'ai dit, laisse moi ton mail et je te le renverrai.

Tout problème a sa solution... Mais en général, c'est jamais la bonne...
3
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
13 avril 2006 à 14:01
Salut,
Bien vu Emandhal pour le fsMDIChild je n'y avais même pas pensé

CptPingu si ça t'intéresse j'ai une version qui fonctionne (grace à Emandhal ) mais qui utilise un Bitmap intermédiaire ce qui donne un très bon résultat.

@+
Cirec
3
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
13 avril 2006 à 22:36
ton probleme reside dans le fait que tu essaye de dessiner en permanance sur l'image. d'ou les problemes.
tu n'utilise aucune structure concrete pour stocker les resultats ce qui est egalement un probleme.
de plus, tu n'a pas besoin d'utiliser autant de fiches ... 1 seule suffit.
ne pas oublier aussi cette regles d'or : si l'applications provoque des erreurs etranges, c'est qu'elle est mal conçue.
voici une exemple vite fait qui te permettras de resoudre les problemes de refresh, je montre ici comment gerer la grille et le dessin de la grille.
J'ai utiliser le type "Object" plutot qu'une classe, mais on peu egalement la definir en classe pour beneficier de plus de puissance et egalement une reutilisation de cette classe.


uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;

type
TForm1 = class(TForm)
Image1: TImage;
procedure FormCreate(Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;

{ pour eviter les debordements }
TMax19 = 1..9;
TMax13 = 1..3;

{ Données des groupes, Rect definit l'emplacement graphique du groupe,
Numbers permet de strocker les 9 nombres de ce groupe et numcols permet
de stocker la couleur a afficher du nombre. cela permet d'assigner des
couleurs particuliere si le nombre est fixe (noir par exemple) si il est
valide (bleu par exemple) ou invalide (rouge par exemple)
le premier indice 1..3 definit le numero de la colone du groupe et le
deuxieme indice le numero de la ligne du groupe :
[1,1] [2,1] [3,1]
[1,2] [2,2] [3,2]
[1,3] [2,3] [3,3]
tout les tableaux respecteront cette regle.
}
TSudokuData = record
Rect : TRect;
numbers : array[1..3,1..3] of TMax19;
numcols : array[1..3,1..3] of TColor;
end;

{ Grilles sudoku complete, Datas contient toute les données de la grille.
Canvas doit etre assigné au canvas de l'image (image.picture.bitmap.canvas)
Draw permet de dessiner la grille sudoku dans l'image.
Update permet de mettre a jours un nombre du groupe gX,gY et de la case nX,nY.
Reset permet de remettre a zero la grille.
Les fonctions Valid** permettent de savoir si le groupe, la ligne ou la colone
contient une serie de nombres valide (1,2,3,4,5,6,7,8,9).
}
TSudokuGrid = object
Datas : array[1..3,1..3] of TSudokuData;
Canvas : TCanvas;
procedure Draw;
procedure Update(gX,gY, nX,nY : TMax13; Num : TMax19; Color : integer);
procedure Reset;
function ValidGroup(gX,gY : TMax13) : boolean;
function ValidRow(i : TMax19) : boolean;
function ValidCol(i : TMax19) : boolean;
end;

var
Form1 : TForm1;
SudObj: TSudokuGrid;

implementation

{$R *.dfm}

{ verifie si le groupe gX,gY est valide }

function TSudokuGrid.ValidGroup(gX,gY : TMax13) : boolean;
var R,Nx,Ny : integer;
TTC : array[1..9] of boolean;
begin
result := true;

{ on initialise TTC par defaut a False }

for R := 1 to 9 do TTC[R] := false;

with Datas[gX,gY] do begin
for nY := 1 to 3 do
for nX := 1 to 3 do begin
if numbers[nX,nY] = 0 then begin

result := false;

exit;

end;

TTC[numbers[nX,nY]] := true;
end;
end;

for R := 1 to 9 do result := (result and TTC[r]);
end;

{ verifie si la ligne i est valide }
function TSudokuGrid.ValidRow(i : TMax19) : boolean;
var Gi,Ni,R,nX,gX : integer;
TTC : array[1..9] of boolean;
begin
result := true;
case i of
1..3:begin Gi := 1; Ni := i; end;
4..6:begin Gi := 2; Ni := i - 3; end;
7..9:begin Gi := 3; Ni := i - 6; end;
end;

for R := 1 to 9 do TTC[R] := false;

with Datas[gX,Gi] do begin
for nX := 1 to 3 do begin
if numbers[nX,ni] = 0 then begin

result := false;

exit;

end;

TTC[numbers[nX,Ni]] := true;
end;
end;
for R := 1 to 9 do result := (result and TTC[r]);
end;

{ verifie si la colone i est valide }
function TSudokuGrid.ValidCol(i : TMax19) : boolean;
var Gi,Ni,R,nY,gY : integer;
TTC : array[1..9] of boolean;
begin
result := true;
case i of
1..3:begin Gi := 1; Ni := i; end;
4..6:begin Gi := 2; Ni := i - 3; end;
7..9:begin Gi := 3; Ni := i - 6; end;
end;

for R := 1 to 9 do TTC[R] := false;

with Datas[Gi,GY] do begin
for nX := 1 to 3 do begin
if numbers[Ni,nY] = 0 then begin

result := false;

exit;

end;

TTC[numbers[Ni,nY]] := true;
end;
end;
for R := 1 to 9 do result := (result and TTC[r]);
end;

{ Mets a jours la case nX,nY du groupe gX,gY
definition du numero a afficher et de la couleur a appliquer. }
procedure TSudokuGrid.Update(gX,gY, nX,nY : TMax13; Num : TMax19; Color : integer);
begin
with Datas[gX,gY] do begin
numbers[nX,nY] := Num;
numcols[nX,nY] := Color;
end;
end;

{ Remet a zero la grille sudoku }
procedure TSudokuGrid.Reset;
var X,Y,Nx,Ny : integer;
begin
for Y := 1 to 3 do
for X := 1 to 3 do begin
with Datas[x,y] do begin
{ definition des rectangles des groupes }
Rect.Left := 3+ (96*(x-1));
Rect.Top := 3+ (96*(y-1));
Rect.Right := 3+ (96*x);
Rect.Bottom := 3+ (96*y);
{ init des numeros a afficher, 0 par defaut }
for Ny := 1 to 3 do
for Nx := 1 to 3 do begin
numbers[Nx,Ny] := 0;
numcols[Nx,Ny] := clBlack;
end;
end;
end;
end;

{ Dessin de la grille, on dessine tout d'un coups et non petit a petit
on utilise egalement un bitmap de buffer pour gagner en performances }
procedure TSudokuGrid.Draw;
var X,Y,Nx,Ny : integer;
S : string;
BMP : TBitmap;
begin
{ creation du buffer de dessin }
BMP := TBitmap.Create;
BMP.Width := 293;
BMP.Height:= 293;

with BMP.Canvas do begin
{ init de la fonte }
Font.Size := 12;
Font.Style := [fsBold];
Font.Name := 'Arial';

{ cadre d'arriere plan }

brush.Style := bsSolid;
brush.Color := clWhite;
pen.Color := $00404080;
pen.Width := 2;
rectangle(1,1,293,293);

for Y := 1 to 3 do begin
for X := 1 to 3 do begin
{ pour le groupe X,Y }

with Datas[X,Y] do begin
{ bsclear permet de rendre le cadre du texte transparent }

brush.Style := bsClear;
pen.Color := clGray;
pen.Width := 1;
for Ny := 1 to 3 do begin
{ on dessine les lignes horizontale }

if NY in [1,2] then begin
MoveTo(Rect.Left, Rect.Top+(32*Ny));
LineTo(Rect.Right,Rect.Top+(32*Ny));
end;
for Nx := 1 to 3 do begin
{ on dessine les lignes verticale }

if Nx in [1,2] then begin
MoveTo(Rect.Left+(32*Nx),Rect.Top);
LineTo(Rect.Left+(32*Nx),Rect.Bottom);
end;
{ si le nombre est different de 0 on dessine le nombre }

s := IntToStr(Numbers[Nx,Ny]);
if S <> '0' then begin
Font.Color := Numcols[Nx,Ny];
{ en le centrant dans la case }

TextOut( (Rect.Left+(32*Nx)) - (TextWidth(S) div 2) - 16,
(Rect.Top +(32*Ny)) - (TextHeight(S) div 2) - 16,
S);
end;
end;
end;
{ et enfin le cadre du groupe }

pen.Color := $00404080;
pen.Width := 2;
rectangle(Rect);
end;
end;
end;
end;
{ on dessine dans le canvas qui a ete assigné }

if assigned(Canvas) then Canvas.Draw(0,0,BMP);
{ on libere le bitmap buffer }

BMP.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
{ on doublebufferise la fiche }

Form1.DoubleBuffered := true;

{ on initialise l'image d'affichage et surtout le bitmap }

image1.Width := 293;
image1.height := 293;
image1.Picture.Bitmap.Width := 293;
image1.Picture.Bitmap.Height := 293;
image1.Picture.Bitmap.pixelformat := pf24bit;

{ assignation du canvas de l'image au canvas de SudObj }
SudObj.Canvas := image1.Picture.Bitmap.Canvas;
{ on reset une fois }
SudObj.Reset;
{ on dessine la grille par defaut }
SudObj.Draw;
end;

end.

Pour resoudre le sudoku, il suffirat de travailler sur Datas[x,y].Numbers[nx,ny], d'assigner les valeur avec la procedure Update, de verifier avec les fonctions Valid** et enfin d'appeler la procedure Draw pour dessiner le resultat.

Enfin, les fichiers de grille pourrait etre stocker dans des fichiers TIniFile pour ameliorer le programme avec une structure de type :
[Group11]
Num11=N

Col11=C
Num12=N

Col12=C
Num13=N

Col13=C


ecriture :

var Ini : TIniFile;
begin
if SaveDialog1.execute then begin
Ini := TIniFile.Create(SaveDialog1.FileName);
for Y := 1 to 3 do
for X := 1 to 3 do
for nY := 1 to 3 do
for nX := 1 to 3 do begin
with SudObj.Datas[X,Y] do begin
WriteInteger( format('Group%d%d',[X,Y]),

format('Num%d%d',[nX,nY]),

Numbers[nX,nY]);

WriteInteger( format('Group%d%d',[X,Y]),

format('Col%d%d',[nX,nY]),

Numcols[nX,nY]);

end;
end;
Ini.Free;
end;
end;

et en lecture :

var Ini : TIniFile;

begin

if OpenDialog1.execute then begin

Ini := TIniFile.Create(OpenDialog1.FileName);

SudObj.Reset;
for Y := 1 to 3 do
for X := 1 to 3 do

for nY := 1 to 3 do
for nX := 1 to 3 do begin

with SudObj.Datas[X,Y] do begin

Numbers[nX,nY] := ReadInteger( format('Group%d%d',[X,Y]),


format('Num%d%d',[nX,nY]), 0);


Numcols[nX,nY] := ReadInteger( format('Group%d%d',[X,Y]),


format('Col%d%d',[nX,nY]), $000000);

end;

end;
Ini.free;
SudObj.Draw;
end;
end;

3
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
12 avril 2006 à 20:18
Salut,
as-tu essayé avec un Application.ProcessMessage

@+
Cirec
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
12 avril 2006 à 20:46
Oui, aussi. Mais ca n'a rien donné.
0
Emandhal Messages postés 194 Date d'inscription dimanche 2 mars 2003 Statut Membre Dernière intervention 10 octobre 2006 3
13 avril 2006 à 13:23
Ton MainForm.FormStyle est en fsMDIChild. Il faut qu'il soit en fsNormal sinon ça ne rafraishissera pas vu que la Form attend que la fsMDIForm lui dise de refresh.

Sinon tu devrais plutot dessiner dans le imgGrille.Picture.Bitmap en ayant au préalable, à la création de la form devrait suffir dans ton cas, fait un :
imgGrille.Picture.Bitmap.Width := imgGrille.Width;
imgGrille.Picture.Bitmap.Height := imgGrille.Height;

Tout problème a sa solution... Mais en général, c'est jamais la bonne...
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
13 avril 2006 à 23:03
Parfait, merci vous 3.
0
Rejoignez-nous