Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.06.2010, 03:59   #1
shumsheec
Пользователь
 
Регистрация: 10.02.2009
Сообщений: 33
По умолчанию Не вызывается OnDrawCell по нажатию правой кнопки мыши

Доброго времени суток всем!
Я увлекаюсь программированием микроконтроллеров, и изредка пишу для себя маленькие вспомогательные программки для ПК на Delphi. Теперь работаю с графическим LCD-дисплеем и подумал, что хорошо было бы написать программку, которая имитировала бы дисплей на экране ПК, в котором можно было бы рисовать (типа как в Paint) а нарисованное через юсб слать в микроконтроллер, чтобы он выводил на дисплей (нужно очень много и долго отлаживать шрифты, размер и цвет картинок и прочее, в коде прошивки это делать крайне неудобно).
Использовал компоненты StringGrid для имитации LCD и для таблицы цветов в восьмибитном формате. Сделал, чтобы можно было выбирать цвет из самодельной палитры, и попиксельно рисовать им на "дисплее". Затем захотел добавить возможность использования фонового цвета (опять же, как в Paint) по нажатию правой кнопки мыши. И возникла проблема. Берётся цвет (и отображается на индикаторной панели цвета фона) сразу же по нажатию, а при нажатии правой кнопкой мыши на "дисплее" сразу не отображается. Приходится либо изменять масштаб "дисплея" (сделано программно), при этом происходит его перерисовка, либо тупо уводить окно с программой за пределы видимой зоны, при входе обратно опять же перерисовывается и цвета отображаются. Не могу понять, в чём дело, вроде бы всё тривиально, гугление и поиск по форуму не помогли, не нашёл ничего подобного.
Вот код обработки нажатия кнопки мыши на импровизированный дисплей:
Код:
procedure TForm1.LCD_StringGridMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
 ACol, ARow: integer;
 rect:TRect;
begin
 with LCD_StringGrid do begin
   MouseToCell (X, Y, ACol, ARow);
      if Button = mbRight then
         color_arr[(ACol-1)+((ARow-1)*176)] := pic_color_bg
      else
  color_arr[(ACol-1)+((ARow-1)*176)] := pic_color;
 end;
end;
Вот код обработки OnDrawCell:
Код:
procedure TForm1.LCD_StringGridDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  i,j,a: byte;
begin
 with LCD_StringGrid do begin
             if gdFixed in State then
     Exit;
             if Cells [ACol, ARow] = '' then begin// если ячейка пустая, берём цвет из массива по вычисляемому адресу
             a := color_arr[(ACol-1)+((ARow-1)*176)];
     Canvas.Brush.Color := rgb(red_arr[a], green_arr[a], blue_arr[a]);
     end;
   Canvas.FillRect (Rect);
   end;
end;
Вот для сравнения код обработки нажатия мыши по "палитре":
Код:
procedure TForm1.ColorMap_StringGridMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
 ACol, ARow: integer;
begin
 with ColorMap_StringGrid do begin
   MouseToCell (X, Y, ACol, ARow);
   if Button = mbRight then
    begin
    pic_color_bg := Acol+(ARow*16);
   BackGroundColor_Panel.Color := rgb(red_arr[pic_color_bg],green_arr[pic_color_bg],blue_arr[pic_color_bg]);
    end
   else
    begin
   pic_color := Acol+(ARow*16);
   CurrentColor_Panel.Color := rgb(red_arr[pic_color],green_arr[pic_color],blue_arr[pic_color]);
    end;
 end;
end;
Код сырой, и с цветами работа, может быть, "извращённая" это потому что на экране отображается цвет в 24-битном формате (конвертированный из 8-битного), а в массиве отдельно хранится в 8-битном, для отправки в микроконтроллер.
Буду очень благодарен за помощь, сам уже не могу понять, почему по проверке условия, какая кнопка мыши нажата, если левая то всё нормально, а если правая, то сам цвет ложится в массив, но канвас не перерисовывается.

Последний раз редактировалось shumsheec; 20.06.2010 в 04:06.
shumsheec вне форума Ответить с цитированием
Старый 20.06.2010, 08:05   #2
Kotofff
Участник клуба
 
Аватар для Kotofff
 
Регистрация: 11.01.2009
Сообщений: 1,917
По умолчанию

Тут немного по-хитрому надо.
Сначала нужно "выловить" ячейку по которой кликнули правой мышкой...
А потом в самом обработчике OnDrawCell смело проверять текущую рисующуюся ячейку на предмет сходства по номеру с той по которой кликнули и рисовать там по нужному алгоритму...
Итак, введем глобальные переменные
Код:
var
  C, R: Integer; // столбец и строка по которым кликнули
Затем, обработчик события OnMouseDown клика правой мышкой :
Код:
procedure TForm1.LCD_StringGridMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  rClick := false;
  if Button = mbRight then // нужна правая клавиша мыши
    begin
    LCD_StringGrid.MouseToCell(x, y, C, R);// у нас есть номер "кликнутой" 
    LCD_StringGrid.Repaint; // принудительно перерисовываем
    end;
end;
И наш обработчик :
Код:
procedure TForm1.LCD_StringGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
  //
  with LCD_StringGrid do
    begin
    if gdFixed in State then Exit;
    if (ACol = C) and (ARow = R) then // проверяем по номеру с "кликнутой" и если она, то рисуем
      begin
      Canvas.Brush.Color := clGray;
      Canvas.FillRect(Rect);
      end;
    end;
end;
Ну, я думаю, что далее сам ...
Спрашивай.
"Заряженному танку в дуло не смотрят" @Dekmer in WoT

Последний раз редактировалось Kotofff; 20.06.2010 в 08:13. Причина: Ошибся ...
Kotofff вне форума Ответить с цитированием
Старый 20.06.2010, 14:05   #3
shumsheec
Пользователь
 
Регистрация: 10.02.2009
Сообщений: 33
По умолчанию

Большое спасибо!
Помогла просто даже эта строчка:
Код:
 LCD_StringGrid.Repaint; // принудительно перерисовываем
непосредственно после обработки нажатия правой кнопкой мышью. Перерисовка происходит незаметно, об оптимальности кода пока не думаю
Буду обращаться ещё, скорее всего, так как в планах создать миниатюрный графический редактор под собственные нужды. Ваш код беру целиком на заметку, пригодится!
shumsheec вне форума Ответить с цитированием
Старый 20.06.2010, 14:10   #4
Kotofff
Участник клуба
 
Аватар для Kotofff
 
Регистрация: 11.01.2009
Сообщений: 1,917
По умолчанию

Ну если понадоблюсь - я тут почти всегда...
"Заряженному танку в дуло не смотрят" @Dekmer in WoT
Kotofff вне форума Ответить с цитированием
Старый 08.07.2010, 03:09   #5
shumsheec
Пользователь
 
Регистрация: 10.02.2009
Сообщений: 33
По умолчанию

Появилась новая необходимость. Как зафиксировать в событии OnMouseMove, что нажата правая или левая кнопка мыши (чтобы при перемещении мыши рисовать линию и т.д.)? Или можно как-то по другому это сделать, в смысле рисовать линии а не отдельные точки?

Дело сдвинулось - обрабатываю
Код:
if (ssleft in shift)
Рисует линию без разрывов, если вести мышью относительно медленно, если быстро водить, то получается штрих-пунктир, видимо, перерисовка на поспевает за курсором. Начинаю подумывать об оптимизации

Последний раз редактировалось shumsheec; 08.07.2010 в 03:59. Причина: догуглил
shumsheec вне форума Ответить с цитированием
Старый 08.07.2010, 15:23   #6
Kotofff
Участник клуба
 
Аватар для Kotofff
 
Регистрация: 11.01.2009
Сообщений: 1,917
По умолчанию

Посмотри пример.
Спрашивай.
Вложения
Тип файла: rar PaintRightButton.rar (7.9 Кб, 20 просмотров)
"Заряженному танку в дуло не смотрят" @Dekmer in WoT
Kotofff вне форума Ответить с цитированием
Старый 15.08.2010, 14:44   #7
shumsheec
Пользователь
 
Регистрация: 10.02.2009
Сообщений: 33
По умолчанию

Kotofff, разобрался в вашем примере, спасибо. Чуть-чуть не подходит, потому как не "запоминаются" старые ячейки, хотя работает быстро.
Возник очередной вопрос - как раскрасить другим цветом выделенные ячейки?
Вот мой текущий обработчик OnDrawCell
Код:
procedure TForm1.LCD_StringGridDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  i,j,a: byte;
  count: integer;
begin
if (FillAll.Tag = 1) then begin
  with LCD_StringGrid do begin
    if gdFixed in State then Exit;
    if (ACol < 177) and (ARow < 133) then begin
      color_arr[(ACol-1)+((ARow-1)*176)] := pic_color;
      canvas.Brush.Color := rgb(red_arr[pic_color], green_arr[pic_color], blue_arr[pic_color]);
      end;
    Canvas.FillRect (Rect);
    end;
  end;

// если выбран карандаш
if pensil.Checked then begin
  with LCD_StringGrid do begin
    if gdFixed in State then Exit;
    if Cells [ACol, ARow] = '' then begin// если ячейка не пустая, берём цвет
      a := color_arr[(ACol-1)+((ARow-1)*176)];
      canvas.Brush.Color := rgb(red_arr[a], green_arr[a], blue_arr[a]);
      end;
    Canvas.FillRect (Rect);
    end;
  end;

// если выбрано "закрасить выбранное"
if FillCurrent.Checked then begin
  with LCD_StringGrid do begin
    if gdFixed in State then
    Exit;
    if Cells [ACol, ARow] = '' then begin // проверяем все ячейки
      a := color_arr[(ACol-1)+((ARow-1)*176)];
      if (a = current_color) then begin
        color_arr[(ACol-1)+((ARow-1)*176)] := pic_color;      // то закрашиваем её основным цветом
        canvas.Brush.Color := rgb(red_arr[pic_color], green_arr[pic_color], blue_arr[pic_color]);
        end
      else  // иначе закрашиваем таким же цветом, как и был
      canvas.Brush.Color := rgb(red_arr[a], green_arr[a], blue_arr[a]);
    end;
    Canvas.FillRect (Rect);
    end;
  end;

if current.Checked then begin
  with LCD_StringGrid do begin
    if gdFixed in State then Exit;
    //if gdFocused in State then Exit;
    if Cells [ACol, ARow] = '' then begin// если ячейка не пустая, берём цвет
      if gdFocused in State then begin
//      a := color_arr[(ACol-1)+((ARow-1)*176)];

      canvas.Brush.Color := rgb(red_arr[100], green_arr[32], blue_arr[69]);
      Canvas.FillRect (Rect);
      end else
      begin
      a := color_arr[(ACol-1)+((ARow-1)*176)];
      canvas.Brush.Color := rgb(red_arr[a], green_arr[a], blue_arr[a]);
      end;
      end;
    Canvas.FillRect (Rect);
    //Canvas.
    end;
  end;

end;
Режим закраски выбирается радиобаттонами. И вот закрасить то, что выделено, не получается, закрашивается только первая из выделяемых ячеек, а дальше всё остаётся как было. Хотя если убрать полностью этот обработчик, то выделенное "закрашивается" белым цветом (то есть, совсем не закрашивается, потому что не задано, как его закрашивать).
И вообще, я уже думаю что стринггрид неоптимален для модели дисплея. Тысячи ячеек получаются, и обрабатывать их долго. А что правильно использовать? Мне нужна масштабируемость (то есть надо чтобы "пикселы" можно было делать размером как 50*50, так и 1*1); чтобы к каждому пикселу можно получить простой доступ и назначить для каждого свой цвет. Какой компонент может это обеспечить? Или может можно как-нибудь "заставить" стринггрид не перерисовываться полностью каждый раз, а лишь перерисовываь ячейки, которые изменили свой цвет?
shumsheec вне форума Ответить с цитированием
Старый 15.08.2010, 15:23   #8
shumsheec
Пользователь
 
Регистрация: 10.02.2009
Сообщений: 33
По умолчанию

Второй раз уже на этом форуме задаю вопрос и почти сразу нахожу ответ, ещё немного поискав
В-общем, завёл четыре переменные, в которые в обработчике движения мыши по стринггриду складываю координаты выделенной области и в обработчике отрисовки по условию
Код:
If ( (((ACol = SelCelLeft) or (ACol > SelCelLeft)) and ((ACol < SelCelRight) or 
(ACol = SelCelRight))) and (((ARow > SelCelTop) or (ARow = SelCelTop)) and 
((ARow < SelCelBottom) or (ARow = SelCelBottom))) )
закрашиваю выделенную область, всё как требовалось. Вылезли мелкие глюки, но общее направление ясно.
Остался вопрос по выбору более оптимального компонента, может быть кто-то делал мини-графические редакторы под свои нужды, подскажет..

Последний раз редактировалось shumsheec; 15.08.2010 в 15:24. Причина: раскинул условие на три строки
shumsheec вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как заставить программу показывать значения по нажатию кнопки мыши xRamzeSx Общие вопросы Delphi 5 17.02.2010 14:03
Как(чем) удалить пункты из меню, которое появляется при нажатии правой кнопки мыши? TwiX Свободное общение 13 11.11.2009 13:53
вывод сообщении только на правой кнопки мыши! KWN, lnc Общие вопросы Delphi 1 21.03.2009 08:26
Косяки с правой кнопкой мыши joker Общие вопросы Delphi 4 12.11.2008 13:25
как вызвать по нажатию кнопки меню настройки клавиатуры, мыши, монитора 1234 Общие вопросы Delphi 2 10.09.2008 16:52