КАПУСТА: почитай,обсуди,отдохни!

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » КАПУСТА: почитай,обсуди,отдохни! » Сеть в DELPHI » Интернетовский чат


Интернетовский чат

Сообщений 11 страница 20 из 33

11

Administrator написал(а):

Все активные модераторы,которые помогают развивать форум тоже его владельцы, так что не напрягайся он и твой :)

Пасибо конечно  ;)

0

12

Вот так можно вставить картинку в формате Bitmap в позицию курсора в TRichEdit:

Код:
 
unit re_bmp;

interface

uses Windows;

procedure InsertBitmapToRE(Wnd:HWND; Bmp:HBITMAP);

implementation

uses Activex, RichEdit;

const

IID_IDataObject: TGUID = (

  D1:$0000010E;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));

IID_IOleObject: TGUID = (

   D1:$00000112;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));

 

REO_CP_SELECTION    = ULONG(-1);

REO_IOB_SELECTION   = ULONG(-1);

REO_GETOBJ_POLEOBJ  =  $00000001;

 

type

TReobject = record

   cbStruct: DWORD;

   cp: ULONG;

   clsid: TCLSID;

   poleobj: IOleObject;

   pstg: IStorage;

   polesite: IOleClientSite;

   sizel: TSize;

   dvAspect: Longint;

   dwFlags: DWORD;

   dwUser: DWORD;

end;

 

type

IRichEditOle = interface(IUnknown)

   ['{00020d00-0000-0000-c000-000000000046}']

   function GetClientSite(out clientSite: IOleClientSite): HResult; stdcall;

   function GetObjectCount: HResult; stdcall;

   function GetLinkCount: HResult; stdcall;

   function GetObject(iob: Longint; out reobject: TReObject;

     dwFlags: DWORD): HResult; stdcall;

   function InsertObject(var reobject: TReObject): HResult; stdcall;

   function ConvertObject(iob: Longint; rclsidNew: TIID;

     lpstrUserTypeNew: LPCSTR): HResult; stdcall;

   function ActivateAs(rclsid: TIID; rclsidAs: TIID): HResult; stdcall;

   function SetHostNames(lpstrContainerApp: LPCSTR;

     lpstrContainerObj: LPCSTR): HResult; stdcall;

   function SetLinkAvailable(iob: Longint; fAvailable: BOOL): HResult; stdcall;

   function SetDvaspect(iob: Longint; dvaspect: DWORD): HResult; stdcall;

   function HandsOffStorage(iob: Longint): HResult; stdcall;

   function SaveCompleted(iob: Longint; const stg: IStorage): HResult; stdcall;

   function InPlaceDeactivate: HResult; stdcall;

   function ContextSensitiveHelp(fEnterMode: BOOL): HResult; stdcall;

   function GetClipboardData(var chrg: TCharRange; reco: DWORD;

     out dataobj: IDataObject): HResult; stdcall;

   function ImportDataObject(dataobj: IDataObject; cf: TClipFormat;

     hMetaPict: HGLOBAL): HResult; stdcall;

end;

 

TImageDataObject=class(TInterfacedObject,IDataObject)

private

  FBmp:HBITMAP;

  FMedium:TStgMedium;

  FFormatEtc: TFormatEtc;

  procedure SetBitmap(bmp:HBITMAP);

  function GetOleObject(OleClientSite:IOleClientSite; Storage:IStorage):IOleObject;

  destructor Destroy;override;

 

  // IDataObject

  function GetData(const formatetcIn: TFormatEtc; out medium: TStgMedium): HResult; stdcall;

   function GetDataHere(const formatetc: TFormatEtc; out medium: TStgMedium): HResult; stdcall;

   function QueryGetData(const formatetc: TFormatEtc): HResult; stdcall;

   function GetCanonicalFormatEtc(const formatetc: TFormatEtc; out formatetcOut: TFormatEtc): HResult; stdcall;

   function SetData(const formatetc: TFormatEtc; var medium: TStgMedium; fRelease: BOOL): HResult; stdcall;

   function EnumFormatEtc(dwDirection: Longint; out enumFormatEtc: IEnumFormatEtc): HResult; stdcall;

   function DAdvise(const formatetc: TFormatEtc; advf: Longint; 

                    const advSink: IAdviseSink; out dwConnection: Longint): HResult; stdcall;

   function DUnadvise(dwConnection: Longint): HResult; stdcall;

   function EnumDAdvise(out enumAdvise: IEnumStatData): HResult; stdcall;

public

  procedure InsertBitmap(wnd:HWND; Bitmap:HBITMAP);

end;

 

 

{ TImageDataObject }

 

function TImageDataObject.DAdvise(const formatetc: TFormatEtc; advf: Integer;

const advSink: IAdviseSink; out dwConnection: Integer): HResult;

begin

Result:=E_NOTIMPL;

end;

 

function TImageDataObject.DUnadvise(dwConnection: Integer): HResult;

begin

Result:=E_NOTIMPL;

end;

 

function TImageDataObject.EnumDAdvise(out enumAdvise: IEnumStatData): HResult;

begin

Result:=E_NOTIMPL;

end;

 

function TImageDataObject.EnumFormatEtc(dwDirection: Integer; out enumFormatEtc: IEnumFormatEtc): HResult;

begin

Result:=E_NOTIMPL;

end;

 

function TImageDataObject.GetCanonicalFormatEtc(const formatetc: TFormatEtc; out formatetcOut: TFormatEtc): HResult;

begin

Result:=E_NOTIMPL;

end;

 

function TImageDataObject.GetDataHere(const formatetc: TFormatEtc; out medium: TStgMedium): HResult;

begin

Result:=E_NOTIMPL;

end;

 

function TImageDataObject.QueryGetData(const formatetc: TFormatEtc): HResult;

begin

Result:=E_NOTIMPL;

end;

 

destructor TImageDataObject.Destroy;

begin

ReleaseStgMedium(FMedium);

end;

 

function TImageDataObject.GetData(const formatetcIn: TFormatEtc; out medium: TStgMedium): HResult;

begin

medium.tymed := TYMED_GDI;

medium.hBitmap :=  FMedium.hBitmap;

medium.unkForRelease := nil;

Result:=S_OK;

end;

 

function TImageDataObject.SetData(const formatetc: TFormatEtc; var medium: TStgMedium; fRelease: BOOL): HResult;

begin

FFormatEtc := formatetc;

FMedium := medium;

Result:= S_OK;

end;

 

procedure TImageDataObject.SetBitmap(bmp: HBITMAP);

var

stgm: TStgMedium;

fm:TFormatEtc;

begin

stgm.tymed := TYMED_GDI;

stgm.hBitmap := bmp;

stgm.UnkForRelease := nil;

 

fm.cfFormat := CF_BITMAP;

fm.ptd := nil;

fm.dwAspect := DVASPECT_CONTENT;

fm.lindex := -1;

fm.tymed := TYMED_GDI;

SetData(fm, stgm, FALSE);

end;

 

function TImageDataObject.GetOleObject(OleClientSite: IOleClientSite; Storage: IStorage):IOleObject;

begin

if (Fmedium.hBitmap=0) then Result:=nil else

OleCreateStaticFromData(self, IID_IOleObject, OLERENDER_FORMAT, @FFormatEtc, OleClientSite, Storage, Result);

end;

 

procedure TImageDataObject.InsertBitmap(wnd:HWND; Bitmap: HBITMAP);

var

OleClientSite:IOleClientSite;

RichEditOLE:IRichEditOLE;

Storage:IStorage;

LockBytes:ILockBytes;

OleObject:IOleObject;

reobject:TReobject;

clsid:TGUID;

begin

if (SendMessage(wnd, EM_GETOLEINTERFACE, 0, cardinal(@RichEditOle))=0) then exit;

 

FBmp:=CopyImage(Bitmap,IMAGE_BITMAP,0,0,0);

if FBmp=0 then exit;

try

  SetBitmap(Fbmp);

  RichEditOle.GetClientSite(OleClientSite);

  if (OleClientSite=nil) then exit;

  CreateILockBytesOnHGlobal(0, TRUE,LockBytes);

  if (LockBytes = nil) then exit;

  if (StgCreateDocfileOnILockBytes(LockBytes, STGM_SHARE_EXCLUSIVE or STGM_CREATE or STGM_READWRITE, 0,Storage)<> S_OK) then

  begin

     LockBytes._Release;

     exit

   end;

 

  if (Storage = nil) then exit;

  OleObject:=GetOleObject(OleClientSite, Storage);

  if (OleObject = nil) then exit;

  OleSetContainedObject(OleObject, TRUE);

 

  ZeroMemory(@reobject, sizeof(TReobject));

  reobject.cbStruct := sizeof(TReobject);

  OleObject.GetUserClassID(clsid);

  reobject.clsid := clsid;

  reobject.cp := REO_CP_SELECTION;

  reobject.dvaspect := DVASPECT_CONTENT;

  reobject.poleobj := OleObject;

  reobject.polesite := OleClientSite;

  reobject.pstg := Storage;

 

  RichEditOle.InsertObject(reobject);

finally

  DeleteObject(FBmp)

end

end;

 

 

procedure InsertBitmapToRE(Wnd:HWND; bmp:HBITMAP);

begin

with TImageDataObject.Create do

try

InsertBitmap(Wnd,Bmp);

finally

Free

end

end;

 

end.

Примеры использования:

Код:
 
uses re_bmp;

 

procedure TForm1.Button1Click(Sender: TObject);

begin

InsertBitmapToRE(RichEdit1.Handle,Image1.Picture.Bitmap.Handle);

end;

 

...

 

procedure TForm1.Button2Click(Sender: TObject);

var

bmp:TBitmap;

begin

if (not OpenPictureDialog1.Execute) then exit;

bmp:=TBitmap.Create;

try

  bmp.LoadFromFile(OpenPictureDialog1.Filename);

  InsertBitmapToRE(RichEdit1.Handle,bmp.Handle);

finally

  bmp.Free

end

end;

Таким же образом можно вставлять картинки не только в TRichEdit, но и в RxRichEdit, стандартный виндовый RichEdit, etc.

От меня: Т.е нужно первый текст впихнуть в модуль а в основной программе его использовать и при вставке использовать функцию, приведённую во втором коде.

0

13

Спасибо!!
Но вот видишь, я вот это сделал в чате и когда я нажимаю картинку со смайлом, то картинка идет в Edit1(TrichEdit), после этого поидее как во всех чатах нужно нажимать ИНТЕР, нажимаю и вот эта картинка должна идти в само окно переписки, КАК ЭТО СДЕЛАТЬ?? поподробнее!!!! и чтоб эта картинка передовалась другому пользователю, а то только у себя я её вижу!!!

0

14

Я как раз столкнулся с этой же проблемой, сейчас думаю как её решить, всё зависит от того: можно ли определьть на какой позиции в тексте стоит картинка, и какая именно, если да, то решается в два счёта, если нет, то придётся думать, как протестирую напишу.

0

15

Ну как там продвижение в работе??

0

16

Пока не было времени... Ты скажи в свойстве Memo1.Text как нибудь можно увидеть картинку, которая вставлена?

0

17

Насчет этого я не знаю!! А че ты не воспользуешься RichEdit???

А по передачи файлов по интернету у тебя есть какая нибудь инфа??

Я вот нашел предачу данных через сокеты, ну че то он не передает

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Image1: TImage;
    Image2: TImage;
    ClientSocket1: TClientSocket;
    ServerSocket1: TServerSocket;
    Button1: TButton;
    procedure Image1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private declarations }
    Reciving: boolean;
    DataSize: integer;
    Data: TMemoryStream;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Image1Click(Sender: TObject);
begin
  // Это процедура для открытия сокета на ПРИЁМ (RECEIVING).
  // Button1.Click is this procedure as well.
  ClientSocket1.Active:= true;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Открытие ОТПРАВЛЯЮЩЕГО (SENDING) сокета.
  ServerSocket1.Active:= true;
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  // Посылаем команду для начала передачи файла.
  Socket.SendText('send');
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  s, sl: string;
begin
  s:= Socket.ReceiveText;
  // Если мы не в режиме приёма:
  if not Reciving then
  begin
    // Теперь нам необходимо получить длину потока данных.
    SetLength(sl, StrLen(PChar(s))+1); // +1 for the null terminator
    StrLCopy(@sl[1], PChar(s), Length(sl)-1);
    DataSize:= StrToInt(sl);
    Data:= TMemoryStream.Create;
    // Удаляем информацию о размере из данных.
    Delete(s, 1, Length(sl));
    Reciving:= true;
  end;
  // Сохраняем данные в файл, до тех пор, пока не получим все данные.
  try
    Data.Write(s[1], length(s));
    if Data.Size = DataSize then
    begin
      Data.Position:= 0;
      Image2.Picture.Bitmap.LoadFromStream(Data);
      Data.Free;
      Reciving:= false;
      Socket.Close;
    end;
  except
    Data.Free;
  end;
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  ms: TMemoryStream;
begin
  // Клиент получает команду на передачу файла.
  if Socket.ReceiveText = 'send' then
  begin
    ms:= TMemoryStream.Create;
    try
      // Получаем данные на передачу.
      Image1.Picture.Bitmap.SaveToStream(ms);
      ms.Position:= 0;
      // Добавляем длину данных, чтобы клиент знал, сколько данных будет передано
      // Добавляем #0 , чтобы можно было определить, где заканчивается информация о размере.
      Socket.SendText(IntToStr(ms.Size) + #0);
      // Посылаем его.
      Socket.SendStream(ms);
    except
      // Итак, осталось освободить поток, если что-то не так.
      ms.Free;
    end;
  end;
end;

end.

0

18

Евгений написал(а):

Насчет этого я не знаю!! А че ты не воспользуешься RichEdit???

Ну это не суть важно Memo, или  RichEdit, главное, чтобы в сойстве было видно картинку.

А разве предыдущий код не работает, который ты мне давно ещё дал?
Я пробовал, работал, давольно удобно там всё сделано. Но в крайнем случае можно и самому написать, тут же всё просто! Отправляющий файл открываешь, и буферами, по килобайту передаёш, принимаюший тут же принимает и пишет в файл, всё ничего сверхестественного нет. Позже посмотрю твой код, и отпишусь.

0

19

Посмотрел твой код, у меня всё работает, только там кнопка не нужна не знаю зачем она введена, видимо из проги выдрано, или тестили прогу. Низнаю смотри у себя. А ты host:=localhost; port:=<любой, но одинаковый у сервера и у клиента> выставил?
Но всё равно код даже в работающем варианте не представляет ценности. Он передаёт одним большим буфером. Вроде передачу с прогресс баром ввести нельзя. Да и оперативу может перегрузить. Да и если файл большой, а передаёт через инет, то придётся прогу держать включеную дня два-три, это не для всех удобно. Я говорю нужно сделать самому с пережачей буфера размером 1Кб. С возможностью докачки. Позже подумаю над этим.

0

20

На счёт отображения смайлов в RichEdit:
Посмотрел, при вставке картинки в RichEdit, в его свойстве Text, весь текст отображается нормально, картинка же отображается почему то кодом пробела, в этом то и проблема, если бы код был уникален, тогда можно было бы однозначно определить что это смайл такой-то, но этого сделать нельзя, как нельзя сделать такую вещь:
RichEdit1.Text:=RichEdit1.Text+'qwerty';, при вставленой картинке, тогда картинка превратится в пробел. Выход из этого есть и как ни странно я его описывал на первой странице этой темы. Нужно просто весь текст держать в переменной, и при его изменении очищать RichEdit, и заново програмно забивать туда уже с картинкой, а RichEdit1.Text:=RichEdit1.Text+'qwerty' можно обойти, и получить тот же результат, вобщем вот код:

Код:
procedure TForm1.Memo1Change(Sender: TObject);
var i:integer;
begin
RichEdit1.Clear;
for i:=1 to length(Memo1.Text) do
if copy(Memo1.Text,i,2)=':)' then
InsertBitmapToRE(RichEdit1.Handle,Image1.Picture.Bitmap.Handle);
else RichEdit1.Perform(WM_CHAR, ord(Memo1.Text[i]),0);
end;

Вобщем на форму ставиш Memo1, RichEdit1, Image1. В Image1 грузиш смайл, пишешь в Memo1, и там уже можно использовать сочетание ": )", и в RichEdit1, отобразится смайл вместо символов!

В коде есть недочёт, за место ": )" заменяется только":", ну думаю разберёшся.
А как передать собеседнику, это нет проблем: на стороне другого клиента точно так же "конвентировать" текст.

0


Вы здесь » КАПУСТА: почитай,обсуди,отдохни! » Сеть в DELPHI » Интернетовский чат