Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 | 3 |

 

  Вопрос: System.Drawing2D.GraphicsState Добавлено: 29.12.08 16:07  

Автор вопроса:  diplay
У меня есть самодельная прога для рисования. Написана на VB.NET. Я хочу сделать в проге возможность отмены последних нескольких действий. Для этого использую объект типа System.Drawing2D.GraphicsState , чтобы сохранять состояние графического объекта, который рисует на самодельном элементе управления. Вот коды, связанные с этим.

Public Class Form1
      Dim actions As GraphicsState() = New GraphicsState(5) {} ' состояния графики на drpPic

' тут остальной код проги

       Private Sub NextAction()
        actions(0) = actions(1)
        actions(1) = actions(2)
        actions(2) = actions(3)
        actions(3) = actions(4)
        actions(4) = actions(5)
        actions(5) = drpPic.AState ' сохранение текущего состояния drpPic
    End Sub

    Private Sub ОтменитьToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ОтменитьToolStripMenuItem.Click
        drpPic.Undo(actions(5)) ' восстановление состояния из массива
        actions(5) = actions(4)
        actions(4) = actions(3)
        actions(3) = actions(2)
        actions(2) = actions(1)
        actions(1) = actions(0)
    End Sub
End Class


Теперь код drpPic
Public Class DrawingPlace
    Dim a As Graphics

    Public Sub InitGraphics()
        a = Me.CreateGraphics
    End Sub

    ' тут остальной код элемента управления
   
    Public ReadOnly Property AState() As Drawing2D.GraphicsState ' возвращает состояние графики
        Get
            Return a.Save
        End Get
    End Property

    Public Sub Undo(ByVal state As GraphicsState) ' восстанавливает состояние графики
        Try
            a.Restore(state)
        Catch
        End Try
    End Sub

End Class

Ответить

  Ответы Всего ответов: 43  

Номер ответа: 1
Автор ответа:
 diplay



Вопросов: 4
Ответов: 69
 Профиль | | #1 Добавлено: 29.12.08 16:08
Что делать? ничего не происходит! я могу если надо выслать весь код.

Ответить

Номер ответа: 2
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #2 Добавлено: 29.12.08 20:48
хм.. что то ты гонишь!
каким образом ты вызвал CreateGraphics в конструкторе, когда у тебя класс не является наследником какого либо контрола с этим методом? Или ты писал свою реализацию CreateGraphics или от чего то унаследовался..

Ответить

Номер ответа: 3
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #3 Добавлено: 29.12.08 21:56
Это было во первых..
Во вторых, предположим что ты все таки от чего то унаследовался.. скажем от Control. В этом случае вызов Me.CreateGraphics в конструкторе класса, маягко говоря, не совсем корректный, и вот почему:
1. В этот момент объекта, как такового, еще не существует, он только создается и еще не инициализировался! Поэтому разумно предположить что объект Graphics будет "пустой" заготовкой. Правильные программеры разделяют подобные вещи на непосредственно сам конструктор и на метод Initialize.
2. Объект Graphics величина не постоянная. Это говорит о том, что при первом же событии OnResize реальный контекст изменится а твой Graphics останется неизменным,что говорит о том, что ты работаешь с копией реального объекта.

Из всего написанного выше ты должен сделать следующие выводы:
- Объект Graphics надо пересоздавать либо по OnResize либо в OnRegionChanged либо получать ссылку в OnPaint
- Правильней всего было бы отказаться от этой безумной затеи(промежуточного хранения Graphics) и использовать Graphics который передается в методе OnPaint

Ответить

Номер ответа: 4
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #4 Добавлено: 29.12.08 22:14
Ну в третьих.. )) что касается реализации метода Undo.
Тут имхо было бы правильней использовать Stack, и использовать что то для промежуточного хранения действий юзера..
Для наглядности набросал простейший примерчик(С#) контрола-рисовалки с реализацией метода Undo
  1.  
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Drawing2D;
  5. using System.Windows.Forms;
  6.  
  7. namespace Orcas.PaintBrush
  8. {
  9.  
  10.     public class PaintControl : Control
  11.     {
  12.         GraphicsPath user_path = new GraphicsPath();
  13.         Stack<GraphicsPath> user_actions = new Stack<GraphicsPath>();
  14.         Point old_location = Point.Empty;
  15.  
  16.         bool is_pressed = false;
  17.  
  18.         public PaintControl()
  19.         {
  20.             this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
  21.             this.UpdateStyles();
  22.         }
  23.  
  24.         protected override void OnPaint(PaintEventArgs e)
  25.         {
  26.             base.OnPaint(e);
  27.             e.Graphics.DrawPath(Pens.Red, user_path);
  28.         }
  29.  
  30.         protected override void OnMouseDown(MouseEventArgs e)
  31.         {
  32.             base.OnMouseDown(e);
  33.             /* add to stack */
  34.             user_actions.Push((GraphicsPath)user_path.Clone());
  35.             old_location = e.Location;
  36.             is_pressed = !is_pressed;
  37.         }
  38.  
  39.         protected override void OnMouseUp(MouseEventArgs e)
  40.         {
  41.             base.OnMouseUp(e);
  42.             is_pressed = !is_pressed;
  43.         }
  44.  
  45.         protected override void OnMouseMove(MouseEventArgs e)
  46.         {
  47.             base.OnMouseMove(e);
  48.             if (is_pressed)
  49.             {
  50.                 user_path.AddLine(old_location, e.Location);
  51.                 user_path.CloseFigure();
  52.                 old_location = e.Location;
  53.                 this.Refresh();
  54.             }
  55.         }
  56.  
  57.         public void Undo()
  58.         {
  59.             user_path.Dispose();
  60.             /* remove from stack */
  61.             user_path = user_actions.Pop();
  62.             this.Refresh();
  63.         }
  64.  
  65.         public bool CanUndo
  66.         {
  67.             get { return (user_actions.Count != 0); }
  68.         }
  69.     }
  70. }

Ответить

Номер ответа: 5
Автор ответа:
 diplay



Вопросов: 4
Ответов: 69
 Профиль | | #5 Добавлено: 30.12.08 15:50
Блин, даже как-то стыдно стало( Я, школьник-самоучка, прихожу на форум к умным людям и, получив умный ответ, не могу въехать в то, что там написано.
Пытаюсь понять.......... прошло 5 минут.
Вроде чё-то понял, щас буду писать. (Если что-то понял неправильно то сильно не ругайте)

Во-первых
Я не знаю, от кого по умолчанию наследуют пользовательские элементы управления в VB.NET. Я просто нажал Проект -> Добавить пользовательский элемент управления. А потом просто стал работать с ним, как с формой. Во всяком случае, он обладает теми же свойствами и методами, что и обычная Windows-форма. Потом он у меня появился в ToolBox'e и я его добавил на форму.

Во-вторых
Метод InitGraphics() не имеет ничего общего с конструктором класса. Он вызывается из формы уже после того, как объект был создан.
Вот:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        drpPic.InitGraphics()
    End Sub

Еще не совсем понял, зачем заново вызывать CreateGraphics() по OnPaint, ведь когда я рисую, я обращаюсь к объекту a, который уже был приравнен к Me.CreateGraphics().

В-третьих
Я не разбираюсь в C#. Попытался все-таки понять. Тока что-такое GraphicPath?

Заключение
Может я немного не так выразился, но в моей проге все работает, просто не пашет отмена действий и все, а так все отлично.

Ответить

Номер ответа: 6
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #6 Добавлено: 30.12.08 17:34
Я не знаю, от кого по умолчанию наследуют пользовательские элементы управления в VB.NET

От класса UserControl
Метод InitGraphics() не имеет ничего общего с конструктором класса

сорри, проглядел и ошибочно принял за конструктор
Еще не совсем понял, зачем заново вызывать CreateGraphics() по OnPaint

Как раз таки наоборот.. вызывать ничего не надо! А надо использовать объект Graphics который передается в событие OnPaint в качестве аргумента (как у меня в строке e.Graphics.DrawPath(Pens.Red, user_path); )
я обращаюсь к объекту a, который уже был приравнен к Me.CreateGraphics()

Да.. так и есть.. но ты должен понимать что это не совсем полноценная ссылка. К примеру ты вызвал CreateGraphics, после этого увеличил размер контрола, и попытайся что нибудь нарисовать на новой(увеличинной) части контрола. Эта часть для тебя будет недоступна, пока ты заново не вызовешь CreateGraphics.
Тока что-такое GraphicPath?

http://msdn.microsoft.com/ru-ru/library/system.drawing.drawing2d.graphicspath.aspx
просто не пашет отмена действий и все, а так все отлично.

А ты чего ожидал? Что твой рисунок вернется к первоначальному состоянию? Старик, ты заблуждаешься.. ты, по всей видимости, не до конца осознаешь предназначение методов Save/Restore. Если верить документации(а мы ей верим, ведь так?) то эти методы сохраняют/ввостанавливают "state of this Graphics object". Т.е. это относится именно к состоянию объекта (если хочешь называй это настройками: способ интерполяции,настройки матрицы преобразования и еще куча других фишек) и никакого отношения к изображению не имеет!

Ответить

Номер ответа: 7
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #7 Добавлено: 30.12.08 17:35
чтобы было более понятно ознакомься с этим документом
http://msdn.microsoft.com/ru-ru/library/system.drawing.graphics.save.aspx

Ответить

Номер ответа: 8
Автор ответа:
 diplay



Вопросов: 4
Ответов: 69
 Профиль | | #8 Добавлено: 30.12.08 18:13
Старик, ты заблуждаешься

Я так и знал...

http://msdn.microsoft.com/ru-ru/library/system.drawing.drawing2d.graphicspath.aspx

Почитал. Я так понял, что объект GraphicsPath представляет из себя совокупность всего что нарисовано на контроле. То есть именно этот объект и надо сохранять.
Я правильно понял?

Ответить

Номер ответа: 9
Автор ответа:
 diplay



Вопросов: 4
Ответов: 69
 Профиль | | #9 Добавлено: 30.12.08 18:21
Еще раз перечитал твой код на С#, теперь вроде разобрался. Тока у тебя челоаек просто рисует мышкой на контроле, а у меня совсем по-другому все устроено. Я лучше на какой-нить файлообменник проект залью и ссылку кину, а ты своими глазами взгляни, а то я так не знаю как объяснить, чтобы понятно было.

Ответить

Номер ответа: 10
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #10 Добавлено: 30.12.08 18:27
объект GraphicsPath представляет из себя совокупность всего что нарисовано на контроле

Не совсем так.. даже, я бы сказал, совсем не так! Это абсолютно самостоятельный объект котрый к контролу никакого отношения не имеет.Контрол просто отрисовывает то, что я(юзер) рисует на этом объекте. Я просто выбрал его в качестве примера, не более того. Ты с таким же успехом можешь создать объект Bitmap(размером с твой контрол) и рисовать на нем и сохранять именно его состояние в стеке, а в OnPaint отрисовывай его(Bitmap) на контроле
Только не забывай вызывать метод Clone() иначе отмена у тебя работать не будет.

Ответить

Номер ответа: 11
Автор ответа:
 diplay



Вопросов: 4
Ответов: 69
 Профиль | | #11 Добавлено: 30.12.08 18:30
вот прога
http://www.sharemania.ru/0187746
писал в Visual Basic .NET Express Edition 2008 RUS

Ответить

Номер ответа: 12
Автор ответа:
 diplay



Вопросов: 4
Ответов: 69
 Профиль | | #12 Добавлено: 30.12.08 18:36
Только не забывай вызывать метод Clone()

Чё за метод Clone()?

Ответить

Номер ответа: 13
Автор ответа:
 diplay



Вопросов: 4
Ответов: 69
 Профиль | | #13 Добавлено: 30.12.08 18:38
Чё за метод Clone()?

Уже понял

Ответить

Номер ответа: 14
Автор ответа:
 diplay



Вопросов: 4
Ответов: 69
 Профиль | | #14 Добавлено: 30.12.08 18:39
А как рисовать на Bitmap? С помощью Graphics? Или как?

Ответить

Номер ответа: 15
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #15 Добавлено: 30.12.08 18:57
А как рисовать на Bitmap? С помощью Graphics? Или как?

да, с помошью Graphics. Создать его можно используя этот метод

public static System.Drawing.Graphics FromImage(System.Drawing.Image image)
    Member of System.Drawing.Graphics

Summary:
Creates a new System.Drawing.Graphics from the specified System.Drawing.Image.

Parameters:
image: System.Drawing.Image from which to create the new System.Drawing.Graphics.

Returns:
This method returns a new System.Drawing.Graphics for the specified System.Drawing.Image.

Ответить

Страница: 1 | 2 | 3 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам