private: // User declarations
void __fastcall LeftFunction(TObject *Sender);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
FAQ's (Старый)
2. Как программно присвоить кнопке обработчик события OnClick?
3. Как скачать файл из Инета?
4. Как на CppWebBrowser запретить вывод стандартное контекстное меню, а заменить его своим?
5. Как выравнять текст в ячейках, столбцах, строках StringGrid?
6. Как при запуске программы узнать путь к exe файлу?
7. Мне нужен динамически созданный CppWebBrowser на всю форму?
8. Как ускорить вывод/загрузку данных в/из Excel?
9. Отловить MouseMove над CppWebBrowser?
10. E2015 Ambiguity between 'function1' and 'function2'. Подскажите что ему надо?
11. Какой компонент, на подобии OpenDialog, нужно использовать, чтобы просто выбрать путь к папке, а не к файлу?
12. Подскажите плиз как в Билдере разбить строку на массив символов по определенному разделителю?
13. Как убрать программу из TaskBarа?
14. Как сделать втопленную кнопку без дополнительных компонентов как через Windows API (свойство WS_BORDER)?
15. Как обрабатывать сообщения окна (WM_*)?
16. При компиляции проекта я получаю сообщение линковщика "Unresolved external" с именем функции и указанием модуля. Как решить проблему?
17. Как можно подключить dll не используя .lib (Вариант - как подключить динамически библиотеку)? Нужно ли ее приводить к типу omf?
18. Как экспортировать класс, форму или фрейм из DLL?
19. Как програмно прокрутить окно Memo на последнюю строку?
20. Как создать Edit для ввода IP адреса, как в свойствах протокола TCP/IP ?
21. Как програмно выровнять колонки у ListView (vsReport) ?
22. Как добавить горизонтальный ScrollBar в ListBox / CheckListBox ?
23. Как проще всего отловить нажатие горячей клавиши,
если окно программы не активно ?
24. Как выделить строку в StringGrid?
25. Как удалить строку/столбец в StringGrid?
26. Как в компонент TWebBrowser загрузить HTML код из строки?
27. Как научить DBGrid слушаться колесико мышки?
28. Как ограничить тип вводимых данных в компонент Edit (нужен только int)?
29. Как удалить файлы по шаблону?
30. Как вызвав, почтового клиента, поместить сразу же туда автоматически текст сообщения и отправителя?
31. Как программно установить BorderIcons. т.е. мне нужно убрать кнопки минимизировать и распахнуть?
32. Загрузка без картинок в CppWebBroser... как?
33. Как программно нажать кнопку на HTML странице?
34. Drag and Drop файлов на форму/компоненту?
35. Как работать со службами(servises)(запустить,остановить,настроить)?
36. Как реализовать доступ к VCL объектам другой программы (внешнего процесса)?
37. Как реализовать поиск по HTML-странице?
- Как сделать в C#, запретить ввод цифр через KeyPress, и вывести окно из сообщение что нужно вводить буквы...? от arkas, 06 июня 2012 года
1. Не запускается готовый exe-файл при переносе на другой компьютер?
Ответ ================================================
Я делаю так:
1. Лезу в Project/Options
2. На вкладке Compiler выбираю Release
3. На вкладке Packages убираю флажок "Build with runtime packages"
4. На вкладке Linker убираю Use Dynamic RTL
5. Компилирую.
Все переносится.
================================================
Автор ответа: Бешеный кролик
===============================================
Вопрос ================================================
2. Как программно присвоить кнопке обработчик события OnClick?
Ответ ================================================
Вот объявление
Код:
Вот определение:
Код:
void __fastcall TForm1::LeftFunction(TObject *Sender){
ShowMessage("Test");
}
ShowMessage("Test");
}
Здесь присвоение
Код:
TForm1->BitBtn2->OnClick = TForm1::LeftFunction;
все.
================================================
Автор ответа: kot_
===============================================
3. Как скачать файл из Инета?
Ответ ================================================
3.1. Вариант 1.
Можно возпользоваться компонентом TIdHTTP с вкладки Indy. Данные компоненты входят в поставку BCB начиная с версии 6.0. Для более ранних версий BCB их можно скачать с оффсайта разработчика: INDY
Код:
void __fastcall TMainForm::GetBtnClick(TObject *Sender)
{
TFileStream* fs;
int ReadByte=0;
int ReadBlock=0;
int NewReadBlock=ReadBlockEd->Text.ToInt();
bool Done=false;
String File=FileEd->Text;
String URL = URLEd->Text;
IdHTTP1->Request->ProxyPassword = PasswordEd->Text;
IdHTTP1->Request->ProxyServer = "ps.proxy.ru";
IdHTTP1->Request->ProxyPort = 3128;
IdHTTP1->Request->ProxyUsername = UserEd->Text;
//если файл ранее уже закачивался...
if(ini->SectionExists(URL)) {
ReadByte = ini->ReadInteger(URL, "ReadByte", 0);
Done = ini->ReadBool(URL, "Done", true);
if(Done) {
ShowMessage(String("Файл закачен полностью. Размер - ") + ReadByte + String(" байт."));
return;
}
ReadBlock = ini->ReadInteger(URL, "ReadBlock", 0);
ReadBlock = (ReadBlock == NewReadBlock)? ReadBlock:NewReadBlock;
File = ini->ReadString(URL, "File", 0);
TFileStream* fs = new TFileStream(File, fmOpenWrite);
fs->Position = ReadByte;
IdHTTP1->Request->ContentRangeStart = ReadByte;
IdHTTP1->Request->ContentRangeEnd = ReadByte + ReadBlock;
IdHTTP1->Get(URL, fs);
if(IdHTTP1->Request->ContentRangeEnd > IdHTTP1->Response->ContentRangeEnd) {
ini->WriteInteger(URL, "ReadByte", IdHTTP1->Response->ContentLength + IdHTTP1->Response->ContentRangeStart);
ini->WriteInteger(URL, "ReadBlock", ReadBlock);
//ini->WriteString(URL, "File", File);
ini->WriteInteger(URL, "Done", true);
}
else {
ini->WriteInteger(URL, "ReadByte", ReadByte + ReadBlock);
ini->WriteInteger(URL, "ReadBlock", ReadBlock);
//ini->WriteString(URL, "File", File);
ini->WriteInteger(URL, "Done", false);
}
delete fs;
}
else {
TFileStream* fs = new TFileStream(File, fmCreate);
fs->Position = ReadByte;
IdHTTP1->Request->ContentRangeStart = ReadByte;
IdHTTP1->Request->ContentRangeEnd = ReadByte + NewReadBlock;
IdHTTP1->Get(URL, fs);
if(IdHTTP1->Request->ContentRangeEnd > IdHTTP1->Response->ContentRangeEnd) {
ini->WriteInteger(URL, "ReadByte", IdHTTP1->Response->ContentLength + IdHTTP1->Response->ContentRangeStart);
ini->WriteInteger(URL, "ReadBlock", NewReadBlock);
ini->WriteString(URL, "File", File);
ini->WriteInteger(URL, "Done", true);
}
else {
ini->WriteInteger(URL, "ReadByte", ReadByte + NewReadBlock);
ini->WriteInteger(URL, "ReadBlock", NewReadBlock);
ini->WriteString(URL, "File", File);
ini->WriteInteger(URL, "Done", false);
}
delete fs;
}
}
{
TFileStream* fs;
int ReadByte=0;
int ReadBlock=0;
int NewReadBlock=ReadBlockEd->Text.ToInt();
bool Done=false;
String File=FileEd->Text;
String URL = URLEd->Text;
IdHTTP1->Request->ProxyPassword = PasswordEd->Text;
IdHTTP1->Request->ProxyServer = "ps.proxy.ru";
IdHTTP1->Request->ProxyPort = 3128;
IdHTTP1->Request->ProxyUsername = UserEd->Text;
//если файл ранее уже закачивался...
if(ini->SectionExists(URL)) {
ReadByte = ini->ReadInteger(URL, "ReadByte", 0);
Done = ini->ReadBool(URL, "Done", true);
if(Done) {
ShowMessage(String("Файл закачен полностью. Размер - ") + ReadByte + String(" байт."));
return;
}
ReadBlock = ini->ReadInteger(URL, "ReadBlock", 0);
ReadBlock = (ReadBlock == NewReadBlock)? ReadBlock:NewReadBlock;
File = ini->ReadString(URL, "File", 0);
TFileStream* fs = new TFileStream(File, fmOpenWrite);
fs->Position = ReadByte;
IdHTTP1->Request->ContentRangeStart = ReadByte;
IdHTTP1->Request->ContentRangeEnd = ReadByte + ReadBlock;
IdHTTP1->Get(URL, fs);
if(IdHTTP1->Request->ContentRangeEnd > IdHTTP1->Response->ContentRangeEnd) {
ini->WriteInteger(URL, "ReadByte", IdHTTP1->Response->ContentLength + IdHTTP1->Response->ContentRangeStart);
ini->WriteInteger(URL, "ReadBlock", ReadBlock);
//ini->WriteString(URL, "File", File);
ini->WriteInteger(URL, "Done", true);
}
else {
ini->WriteInteger(URL, "ReadByte", ReadByte + ReadBlock);
ini->WriteInteger(URL, "ReadBlock", ReadBlock);
//ini->WriteString(URL, "File", File);
ini->WriteInteger(URL, "Done", false);
}
delete fs;
}
else {
TFileStream* fs = new TFileStream(File, fmCreate);
fs->Position = ReadByte;
IdHTTP1->Request->ContentRangeStart = ReadByte;
IdHTTP1->Request->ContentRangeEnd = ReadByte + NewReadBlock;
IdHTTP1->Get(URL, fs);
if(IdHTTP1->Request->ContentRangeEnd > IdHTTP1->Response->ContentRangeEnd) {
ini->WriteInteger(URL, "ReadByte", IdHTTP1->Response->ContentLength + IdHTTP1->Response->ContentRangeStart);
ini->WriteInteger(URL, "ReadBlock", NewReadBlock);
ini->WriteString(URL, "File", File);
ini->WriteInteger(URL, "Done", true);
}
else {
ini->WriteInteger(URL, "ReadByte", ReadByte + NewReadBlock);
ini->WriteInteger(URL, "ReadBlock", NewReadBlock);
ini->WriteString(URL, "File", File);
ini->WriteInteger(URL, "Done", false);
}
delete fs;
}
}
3.2. Вариант 2.
Воспользоваться функциями WinInet. Необходимо включить хедер wininet.h и подключить к проекту файл $(BCB)\LIB\PSDK\wininet.lib
Код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
char szUrl[] = "http://www.codenet.ru";
//String Page;
HINTERNET hInternet = InternetOpen("MY AGENT",
INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET hRequest = InternetOpenUrl(hInternet, szUrl, NULL, 0, 0, 0);
if(hRequest)
{
DWORD dwRead;
char szTemp[1024];
TFileStream* fs = new TFileStream(ExtractFilePath(Application->ExeName) + "\\Page.html", fmCreate);
while (InternetReadFile(hRequest, (LPVOID)szTemp, 1024, &dwRead))
{
if (!dwRead) break;
fs->Write(szTemp, dwRead);
//Page = Page + String(szTemp);
}
delete fs;
}
InternetCloseHandle(hRequest);
InternetCloseHandle(hInternet);
}
{
char szUrl[] = "http://www.codenet.ru";
//String Page;
HINTERNET hInternet = InternetOpen("MY AGENT",
INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET hRequest = InternetOpenUrl(hInternet, szUrl, NULL, 0, 0, 0);
if(hRequest)
{
DWORD dwRead;
char szTemp[1024];
TFileStream* fs = new TFileStream(ExtractFilePath(Application->ExeName) + "\\Page.html", fmCreate);
while (InternetReadFile(hRequest, (LPVOID)szTemp, 1024, &dwRead))
{
if (!dwRead) break;
fs->Write(szTemp, dwRead);
//Page = Page + String(szTemp);
}
delete fs;
}
InternetCloseHandle(hRequest);
InternetCloseHandle(hInternet);
}
3.3 Вариант 3.
Непосредственно юзать WinSock API. Например скачиваем страницу и помещаем ее содержимое в Memo.
Код:
//Winsock API
char request[]=
"GET / HTTP/1.0\r\n\
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n\
Accept-Language: ru\r\n\
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)\r\n\
Host: www.codenet.ru\r\n\r\n";
#define MAX_PACKET_SIZE 4096
void __fastcall TForm1::Button3Click(TObject *Sender)
{
WSADATA ws;
SOCKET s;
sockaddr_in adr;
hostent* hn;
char buff [MAX_PACKET_SIZE];
// Init
if (WSAStartup (0x0101, &ws) != 0)
{
// Error
return;
}
// Создаем сокет
if (INVALID_SOCKET == (s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ) )
{
// Error
return;
}
// получаем ИП
if (NULL == ( hn = gethostbyname ("www.codenet.ru") ) )
{
// Error
return;
}
// Заполгняем структуру
adr.sin_family = AF_INET;
adr.sin_addr.S_un.S_addr = *(DWORD* ) hn->h_addr_list[0];
adr.sin_port = htons (80);
// Устанавливаем соединение
if (SOCKET_ERROR == connect (s, (sockaddr* )&adr, sizeof (adr) ) )
{
// Error
return;
}
// Посылаем запрос
if (SOCKET_ERROR == send (s, request, strlen(request), 0) )
{
// Error
return;
}
// Принимаем данные
int len;
do
{
if (SOCKET_ERROR == (len = recv (s, (char *) &buff, MAX_PACKET_SIZE, 0) ) )
return;
Memo1->Lines->Add(buff);
}
while (len!=0);
/*int len = recv (s, (char *) &buff, MAX_PACKET_SIZE, 0);
if ( (len == SOCKET_ERROR) || (len == 0) )
{
// Error
return ;
}
// Выводим полученное
Memo1->Lines->Add(buff);*/
// Cae?uaaai niaaeiaiea
if (SOCKET_ERROR == closesocket (s) )
{
// Error
return ;
}
}
char request[]=
"GET / HTTP/1.0\r\n\
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n\
Accept-Language: ru\r\n\
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)\r\n\
Host: www.codenet.ru\r\n\r\n";
#define MAX_PACKET_SIZE 4096
void __fastcall TForm1::Button3Click(TObject *Sender)
{
WSADATA ws;
SOCKET s;
sockaddr_in adr;
hostent* hn;
char buff [MAX_PACKET_SIZE];
// Init
if (WSAStartup (0x0101, &ws) != 0)
{
// Error
return;
}
// Создаем сокет
if (INVALID_SOCKET == (s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ) )
{
// Error
return;
}
// получаем ИП
if (NULL == ( hn = gethostbyname ("www.codenet.ru") ) )
{
// Error
return;
}
// Заполгняем структуру
adr.sin_family = AF_INET;
adr.sin_addr.S_un.S_addr = *(DWORD* ) hn->h_addr_list[0];
adr.sin_port = htons (80);
// Устанавливаем соединение
if (SOCKET_ERROR == connect (s, (sockaddr* )&adr, sizeof (adr) ) )
{
// Error
return;
}
// Посылаем запрос
if (SOCKET_ERROR == send (s, request, strlen(request), 0) )
{
// Error
return;
}
// Принимаем данные
int len;
do
{
if (SOCKET_ERROR == (len = recv (s, (char *) &buff, MAX_PACKET_SIZE, 0) ) )
return;
Memo1->Lines->Add(buff);
}
while (len!=0);
/*int len = recv (s, (char *) &buff, MAX_PACKET_SIZE, 0);
if ( (len == SOCKET_ERROR) || (len == 0) )
{
// Error
return ;
}
// Выводим полученное
Memo1->Lines->Add(buff);*/
// Cae?uaaai niaaeiaiea
if (SOCKET_ERROR == closesocket (s) )
{
// Error
return ;
}
}
3.4. И самый простой вариант.
Воспользоваться ф-ией URLDownloadToFile. Необходимо включить хедер urlmon.h и подключить к проекту файл $(BCB)\LIB\PSDK\urlmon.lib
Код:
URLDownloadToFile( 0, "http://www.codenet.ru", "c:\\temp\myfile.html", 0, 0);
================================================
Автор ответа: GIZMO
===============================================
4. Как на CppWebBrowser запретить(изменить) вывод стандартного контекстного меню?
Ответ:
Реализуете собственный интерфейс IDocHostUIHandler главным образом его метод ShowContextMenu создать свое меню и вернуть S_OK чтобы браузер "понял о чем его просят". Устанавливаете его с помощью ICustomDoc::SetUIHandler.
Ниже приведен пример изменения контекстного меню, замена намного проще.
================================================
Код:
// in hpp
#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Menus.hpp>
#include "mshtmhst.h"
#include "mshtmcid.h"
#include "atlbase.h"
#include "SHDocVw_OCX.h"
#include <OleCtrls.hpp>
//---------------------------------------------------------------------------
class TDocHandler : public IDocHostUIHandler
{
long refcount;
public:
TDocHandler():refcount(1){};
//IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID classid, void** intf) {
if (classid == IID_IUnknown)
*intf = (IUnknown*)this;
else if (classid == IID_IDocHostUIHandler)
*intf = (IDocHostUIHandler*)this;
else
return E_NOINTERFACE;
return S_OK;
}
virtual ULONG STDMETHODCALLTYPE AddRef() {
InterlockedIncrement(&refcount);
return refcount;
}
virtual ULONG STDMETHODCALLTYPE Release() {
InterlockedDecrement(&refcount);
if (refcount == 0)
delete this;
return refcount;
}
//IDocHostUIHandler
// Чтобы отключить контекстное меню надо вернуть S_OK
virtual HRESULT STDMETHODCALLTYPE ShowContextMenu(
/* [in] */ DWORD dwID,
/* [in] */ POINT __RPC_FAR *ppt,
/* [in] */ IUnknown __RPC_FAR *pcmdtReserved,
/* [in] */ IDispatch __RPC_FAR *pdispReserved) {
#define IDR_BROWSE_CONTEXT_MENU 24641
#define IDR_FORM_CONTEXT_MENU 24640
#define SHDVID_GETMIMECSETMENU 27
#define SHDVID_ADDMENUEXTENSIONS 53
HRESULT hr;
HINSTANCE hinstSHDOCLC;
HWND hwnd;
HMENU hMenu;
CComPtr<IOleCommandTarget> spCT;
CComPtr<IOleWindow> spWnd;
MENUITEMINFO mii = {0};
CComVariant var, var1, var2;
hr = pcmdtReserved->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
hr = pcmdtReserved->QueryInterface(IID_IOleWindow, (void**)&spWnd);
hr = spWnd->GetWindow(&hwnd);
hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL"));
hMenu = LoadMenu(hinstSHDOCLC,
MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
hMenu = GetSubMenu(hMenu, dwID);
// Iieo?aai iiaiai? aey ycueia eiae?iaee
hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU;
mii.hSubMenu = (HMENU) var.byref;
// Caiieiyai iai? Aea eiae?iaee
SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);
// Oaaeyai ioieo iai? Iieacaou a aeaa HTML
DeleteMenu(hMenu, IDM_VIEWSOURCE, MF_BYCOMMAND);
int iSelection = ::TrackPopupMenu(hMenu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, ppt->x, ppt->y, 0, hwnd, (RECT*)NULL);
// Ia?anueaai aua?aiio? eiiaiao ieio a?ioca?a
LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
FreeLibrary(hinstSHDOCLC);
return S_OK;
// Return S_OK to tell MSHTML not to display its own menu
// Return S_FALSE displays default MSHTML menu
}
virtual HRESULT STDMETHODCALLTYPE GetHostInfo(
/* [out][in] */ DOCHOSTUIINFO __RPC_FAR *pInfo) {
if (pInfo == NULL)
return E_POINTER;
pInfo->cbSize = sizeof(DOCHOSTUIINFO);
pInfo->dwFlags &= ~DOCHOSTUIFLAG_DIALOG;
/*DOCHOSTUIFLAG_DIALOG
MSHTML does not enable selection of the text in the form
*/
return S_OK;
// return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE ShowUI(
/* [in] */ DWORD dwID,
/* [in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
/* [in] */ IOleCommandTarget __RPC_FAR *pCommandTarget,
/* [in] */ IOleInPlaceFrame __RPC_FAR *pFrame,
/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pDoc) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE HideUI( void) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE UpdateUI( void) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE EnableModeless(
/* [in] */ BOOL fEnable) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate(
/* [in] */ BOOL fActivate) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(
/* [in] */ BOOL fActivate) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE ResizeBorder(
/* [in] */ LPCRECT prcBorder,
/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
/* [in] */ BOOL fRameWindow) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(
/* [in] */ LPMSG lpMsg,
/* [in] */ const GUID __RPC_FAR *pguidCmdGroup,
/* [in] */ DWORD nCmdID) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetOptionKeyPath(
/* [out] */ LPOLESTR __RPC_FAR *pchKey,
/* [in] */ DWORD dw) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetDropTarget(
/* [in] */ IDropTarget __RPC_FAR *pDropTarget,
/* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetExternal(
/* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE TranslateUrl(
/* [in] */ DWORD dwTranslate,
/* [in] */ OLECHAR __RPC_FAR *pchURLIn,
/* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE FilterDataObject(
/* [in] */ IDataObject __RPC_FAR *pDO,
/* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet) {
return E_NOTIMPL;
}
};
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TCppWebBrowser *CppWebBrowser1;
void __fastcall CppWebBrowser1NavigateComplete2(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL);
void __fastcall CppWebBrowser1DocumentComplete(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL);
private: // User declarations
TDocHandler* dochandler;
_di_IDispatch CurDispatch;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
public:
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
// in cpp
#include <vcl.h>
#pragma hdrstop
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "SHDocVw_OCX"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
dochandler = new TDocHandler();
CppWebBrowser1->GoHome();
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1() {
dochandler->Release();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CppWebBrowser1NavigateComplete2(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL)
{
if (!CurDispatch)
CurDispatch = pDisp; // save for comparison
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CppWebBrowser1DocumentComplete(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL)
{
if (CurDispatch && pDisp == CurDispatch)
{
// the document is loaded, not just a frame
CurDispatch = NULL; //clear the global variable
// Set this class to be the IDocHostUIHandler
CComQIPtr<ICustomDoc, &IID_ICustomDoc> pCustomDoc(CppWebBrowser1->Document);
if (pCustomDoc)
pCustomDoc->SetUIHandler(dochandler);
}
}
//---------------------------------------------------------------------------
#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Menus.hpp>
#include "mshtmhst.h"
#include "mshtmcid.h"
#include "atlbase.h"
#include "SHDocVw_OCX.h"
#include <OleCtrls.hpp>
//---------------------------------------------------------------------------
class TDocHandler : public IDocHostUIHandler
{
long refcount;
public:
TDocHandler():refcount(1){};
//IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID classid, void** intf) {
if (classid == IID_IUnknown)
*intf = (IUnknown*)this;
else if (classid == IID_IDocHostUIHandler)
*intf = (IDocHostUIHandler*)this;
else
return E_NOINTERFACE;
return S_OK;
}
virtual ULONG STDMETHODCALLTYPE AddRef() {
InterlockedIncrement(&refcount);
return refcount;
}
virtual ULONG STDMETHODCALLTYPE Release() {
InterlockedDecrement(&refcount);
if (refcount == 0)
delete this;
return refcount;
}
//IDocHostUIHandler
// Чтобы отключить контекстное меню надо вернуть S_OK
virtual HRESULT STDMETHODCALLTYPE ShowContextMenu(
/* [in] */ DWORD dwID,
/* [in] */ POINT __RPC_FAR *ppt,
/* [in] */ IUnknown __RPC_FAR *pcmdtReserved,
/* [in] */ IDispatch __RPC_FAR *pdispReserved) {
#define IDR_BROWSE_CONTEXT_MENU 24641
#define IDR_FORM_CONTEXT_MENU 24640
#define SHDVID_GETMIMECSETMENU 27
#define SHDVID_ADDMENUEXTENSIONS 53
HRESULT hr;
HINSTANCE hinstSHDOCLC;
HWND hwnd;
HMENU hMenu;
CComPtr<IOleCommandTarget> spCT;
CComPtr<IOleWindow> spWnd;
MENUITEMINFO mii = {0};
CComVariant var, var1, var2;
hr = pcmdtReserved->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
hr = pcmdtReserved->QueryInterface(IID_IOleWindow, (void**)&spWnd);
hr = spWnd->GetWindow(&hwnd);
hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL"));
hMenu = LoadMenu(hinstSHDOCLC,
MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
hMenu = GetSubMenu(hMenu, dwID);
// Iieo?aai iiaiai? aey ycueia eiae?iaee
hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU;
mii.hSubMenu = (HMENU) var.byref;
// Caiieiyai iai? Aea eiae?iaee
SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);
// Oaaeyai ioieo iai? Iieacaou a aeaa HTML
DeleteMenu(hMenu, IDM_VIEWSOURCE, MF_BYCOMMAND);
int iSelection = ::TrackPopupMenu(hMenu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, ppt->x, ppt->y, 0, hwnd, (RECT*)NULL);
// Ia?anueaai aua?aiio? eiiaiao ieio a?ioca?a
LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
FreeLibrary(hinstSHDOCLC);
return S_OK;
// Return S_OK to tell MSHTML not to display its own menu
// Return S_FALSE displays default MSHTML menu
}
virtual HRESULT STDMETHODCALLTYPE GetHostInfo(
/* [out][in] */ DOCHOSTUIINFO __RPC_FAR *pInfo) {
if (pInfo == NULL)
return E_POINTER;
pInfo->cbSize = sizeof(DOCHOSTUIINFO);
pInfo->dwFlags &= ~DOCHOSTUIFLAG_DIALOG;
/*DOCHOSTUIFLAG_DIALOG
MSHTML does not enable selection of the text in the form
*/
return S_OK;
// return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE ShowUI(
/* [in] */ DWORD dwID,
/* [in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
/* [in] */ IOleCommandTarget __RPC_FAR *pCommandTarget,
/* [in] */ IOleInPlaceFrame __RPC_FAR *pFrame,
/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pDoc) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE HideUI( void) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE UpdateUI( void) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE EnableModeless(
/* [in] */ BOOL fEnable) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate(
/* [in] */ BOOL fActivate) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(
/* [in] */ BOOL fActivate) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE ResizeBorder(
/* [in] */ LPCRECT prcBorder,
/* [in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
/* [in] */ BOOL fRameWindow) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(
/* [in] */ LPMSG lpMsg,
/* [in] */ const GUID __RPC_FAR *pguidCmdGroup,
/* [in] */ DWORD nCmdID) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetOptionKeyPath(
/* [out] */ LPOLESTR __RPC_FAR *pchKey,
/* [in] */ DWORD dw) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetDropTarget(
/* [in] */ IDropTarget __RPC_FAR *pDropTarget,
/* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetExternal(
/* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE TranslateUrl(
/* [in] */ DWORD dwTranslate,
/* [in] */ OLECHAR __RPC_FAR *pchURLIn,
/* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE FilterDataObject(
/* [in] */ IDataObject __RPC_FAR *pDO,
/* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet) {
return E_NOTIMPL;
}
};
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TCppWebBrowser *CppWebBrowser1;
void __fastcall CppWebBrowser1NavigateComplete2(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL);
void __fastcall CppWebBrowser1DocumentComplete(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL);
private: // User declarations
TDocHandler* dochandler;
_di_IDispatch CurDispatch;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
public:
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
// in cpp
#include <vcl.h>
#pragma hdrstop
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "SHDocVw_OCX"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
dochandler = new TDocHandler();
CppWebBrowser1->GoHome();
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1() {
dochandler->Release();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CppWebBrowser1NavigateComplete2(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL)
{
if (!CurDispatch)
CurDispatch = pDisp; // save for comparison
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CppWebBrowser1DocumentComplete(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL)
{
if (CurDispatch && pDisp == CurDispatch)
{
// the document is loaded, not just a frame
CurDispatch = NULL; //clear the global variable
// Set this class to be the IDocHostUIHandler
CComQIPtr<ICustomDoc, &IID_ICustomDoc> pCustomDoc(CppWebBrowser1->Document);
if (pCustomDoc)
pCustomDoc->SetUIHandler(dochandler);
}
}
//---------------------------------------------------------------------------
================================================
Автор ответа: GIZMO
===============================================
Вопрос ================================================
5. Как выравнять текст в ячейках, столбцах, строках StringGrid?
Ответ:
Код:
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
int ARow, TRect &Rect, TGridDrawState State)
{
UINT uFormat = DT_LEFT | DT_VCENTER /*| DT_WORDBREAK*/ ; //по умолчанию влево
switch (ACol)
{
case 1:
uFormat = DT_CENTER | DT_VCENTER ;//по центру
break;
case 2:
case 4:
uFormat = DT_RIGHT | DT_VCENTER ;//вправо
break;
}
StringGrid1->Canvas->FillRect(Rect);
DrawText(StringGrid1->Canvas->Handle, // handle to device context
StringGrid1->Cells[ACol][ARow].c_str(), // pointer to string to draw
StringGrid1->Cells[ACol][ARow].Length(), // string length, in characters
&Rect, // pointer to structure with formatting dimensions
uFormat // text-drawing flags
);
}
int ARow, TRect &Rect, TGridDrawState State)
{
UINT uFormat = DT_LEFT | DT_VCENTER /*| DT_WORDBREAK*/ ; //по умолчанию влево
switch (ACol)
{
case 1:
uFormat = DT_CENTER | DT_VCENTER ;//по центру
break;
case 2:
case 4:
uFormat = DT_RIGHT | DT_VCENTER ;//вправо
break;
}
StringGrid1->Canvas->FillRect(Rect);
DrawText(StringGrid1->Canvas->Handle, // handle to device context
StringGrid1->Cells[ACol][ARow].c_str(), // pointer to string to draw
StringGrid1->Cells[ACol][ARow].Length(), // string length, in characters
&Rect, // pointer to structure with formatting dimensions
uFormat // text-drawing flags
);
}
6. Как при запуске программы узнать путь к exe файлу?
Ответ ================================================
Код:
Вариант 1.
String Path = ExtractFilePath(ParamStr(0));
Вариант 2.
AnsiString Path;
Path = ExtractFilePath(Application->ExeName);
String Path = ExtractFilePath(ParamStr(0));
Вариант 2.
AnsiString Path;
Path = ExtractFilePath(Application->ExeName);
================================================
Автор ответа: 1 kot_, 2 enola
===============================================
Вопрос ================================================
7. Мне нужен динамически созданный CppWebBrowser на всю форму?
Ответ ================================================
Код:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TCppWebBrowser *CppWebBrowser = new TCppWebBrowser ( this );
CppWebBrowser->TOleControl::Parent = this;
CppWebBrowser->Align = alClient;
CppWebBrowser->Navigate(WideString("http://forum.codenet.ru/newreply.php?do=newreply&p=124529"));
}
{
TCppWebBrowser *CppWebBrowser = new TCppWebBrowser ( this );
CppWebBrowser->TOleControl::Parent = this;
CppWebBrowser->Align = alClient;
CppWebBrowser->Navigate(WideString("http://forum.codenet.ru/newreply.php?do=newreply&p=124529"));
}
================================================
Автор ответа: *****
===============================================
Вопрос ================================================
8. Как ускорить вывод/загрузку данных в/из Excel?
Ответ ================================================
8.1 Вариант 1. Вставлять сразу диапазонами, а не в каждую ячейку:
Код:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
TDateTime tm1, tm2;
String Range;
Variant A(OPENARRAY(int, (0, StringGrid1->ColCount)), varVariant);
tm1 = Time();
XL = CreateOleObject("Excel.Application.8");
XL.OlePropertySet("Visible", CheckBox1->Checked);
v0 = XL.OlePropertyGet("Workbooks");
v0.OleProcedure("Add");
v1 = v0.OlePropertyGet("Item", 1).OlePropertyGet("Worksheets").OlePropertyGet("Item", 1);
for (int i = 0; i < StringGrid1->RowCount; i++) {
for (int j = 0; j < StringGrid1->ColCount; j++) {
A.PutElement(StringGrid1->Cells[j],j);
}
Range.printf("A%d:J%d", i+1, i+1);
v1.OlePropertyGet("Range", Range.c_str()).OlePropertySet("Value", A);
}
XL.OlePropertySet("DisplayAlerts",false);
XL.OlePropertyGet("Workbooks").OlePropertyGet("Item",1).OleProcedure("SaveAs", ChangeFileExt(Application->ExeName, ".xls"));
XL.OleProcedure("Quit");
tm2 = Time();
ShowMessage("done with " + TimeToStr(tm2 - tm1));
}
{
TDateTime tm1, tm2;
String Range;
Variant A(OPENARRAY(int, (0, StringGrid1->ColCount)), varVariant);
tm1 = Time();
XL = CreateOleObject("Excel.Application.8");
XL.OlePropertySet("Visible", CheckBox1->Checked);
v0 = XL.OlePropertyGet("Workbooks");
v0.OleProcedure("Add");
v1 = v0.OlePropertyGet("Item", 1).OlePropertyGet("Worksheets").OlePropertyGet("Item", 1);
for (int i = 0; i < StringGrid1->RowCount; i++) {
for (int j = 0; j < StringGrid1->ColCount; j++) {
A.PutElement(StringGrid1->Cells[j],j);
}
Range.printf("A%d:J%d", i+1, i+1);
v1.OlePropertyGet("Range", Range.c_str()).OlePropertySet("Value", A);
}
XL.OlePropertySet("DisplayAlerts",false);
XL.OlePropertyGet("Workbooks").OlePropertyGet("Item",1).OleProcedure("SaveAs", ChangeFileExt(Application->ExeName, ".xls"));
XL.OleProcedure("Quit");
tm2 = Time();
ShowMessage("done with " + TimeToStr(tm2 - tm1));
}
8.2 Вариант 2. Сформировать строковый массив, слова в строках д.б. разделены символом табуляции и все это вставить через Clipboard.
Код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TStringList* data = new TStringList();
String line;
TDateTime tm1, tm2;
tm1 = Time();
//вставим в Excel...
XL = CreateOleObject("Excel.Application.8");
XL.OlePropertySet("Visible", CheckBox1->Checked);
v0 = XL.OlePropertyGet("Workbooks");
v0.OleProcedure("Add");
v1 = v0.OlePropertyGet("Item", 1).OlePropertyGet("Worksheets").OlePropertyGet("Item", 1);
//добавляем строки в которых слова разделены Tab-ом, Excel - поймет...
for (int i = 0; i < StringGrid1->RowCount; i++) {
line = StringGrid1->Cells[0];
for (int j = 1; j < StringGrid1->ColCount; j++) {
line = line + "\t" + StringGrid1->Cells[j];
}
data->Add(line);
}
//в Clipboard...
Clipboard()->AsText = data->Text;
v1.OlePropertyGet("Range", "A1:A1").OleProcedure("Select"); //например начиная с этой ячейки...
v1.OleProcedure("Paste");
Clipboard()->Clear();
XL.OlePropertySet("DisplayAlerts",false);
XL.OlePropertyGet("Workbooks").OlePropertyGet("Item",1).OleProcedure("SaveAs", ChangeFileExt(Application->ExeName, ".xls"));
XL.OleProcedure("Quit");
tm2 = Time();
ShowMessage("done with " + TimeToStr(tm2 - tm1));
delete data;
}
{
TStringList* data = new TStringList();
String line;
TDateTime tm1, tm2;
tm1 = Time();
//вставим в Excel...
XL = CreateOleObject("Excel.Application.8");
XL.OlePropertySet("Visible", CheckBox1->Checked);
v0 = XL.OlePropertyGet("Workbooks");
v0.OleProcedure("Add");
v1 = v0.OlePropertyGet("Item", 1).OlePropertyGet("Worksheets").OlePropertyGet("Item", 1);
//добавляем строки в которых слова разделены Tab-ом, Excel - поймет...
for (int i = 0; i < StringGrid1->RowCount; i++) {
line = StringGrid1->Cells[0];
for (int j = 1; j < StringGrid1->ColCount; j++) {
line = line + "\t" + StringGrid1->Cells[j];
}
data->Add(line);
}
//в Clipboard...
Clipboard()->AsText = data->Text;
v1.OlePropertyGet("Range", "A1:A1").OleProcedure("Select"); //например начиная с этой ячейки...
v1.OleProcedure("Paste");
Clipboard()->Clear();
XL.OlePropertySet("DisplayAlerts",false);
XL.OlePropertyGet("Workbooks").OlePropertyGet("Item",1).OleProcedure("SaveAs", ChangeFileExt(Application->ExeName, ".xls"));
XL.OleProcedure("Quit");
tm2 = Time();
ShowMessage("done with " + TimeToStr(tm2 - tm1));
delete data;
}
пример загрузки через Clipboard и Range см. вложение.
================================================
Автор ответа: GIZMO
===============================================
Вопрос ================================================
9. Отловить MouseMove над CppWebBrowser ?
Ответ ================================================
Код:
// in hpp
#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "mshtml.h"
#include "mshtmdid.h"
#include "SHDocVw_OCX.h"
#include <OleCtrls.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
typedef void __fastcall (__closure *TOnMouseMove)();
//---------------------------------------------------------------------------
class THtmlEventSink : public IDispatch
{
protected:
TOnMouseMove FOnMouseMove;
public:
THtmlEventSink() { m_cRef = 0; }
~THtmlEventSink() { /*ShowMessage("~THtmlEventSink()");*/} // trace it work
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject)
{
*ppvObject = NULL;
if (IsEqualGUID(riid, IID_IUnknown))
*ppvObject = reinterpret_cast<void**>(this);
if (IsEqualGUID(riid, IID_IDispatch))
*ppvObject = reinterpret_cast<void**>(this);
if (*ppvObject)
{
((IUnknown*)*ppvObject)->AddRef();
return S_OK;
}
else return E_NOINTERFACE;
}
DWORD __stdcall AddRef()
{
return InterlockedIncrement(&m_cRef);
}
DWORD __stdcall Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo)
{ return E_NOTIMPL; }
STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo)
{ return E_NOTIMPL; }
STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId)
{ return S_OK; }
STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO * pExcepInfo, UINT * puArgErr)
{
if (FOnMouseMove != NULL)
FOnMouseMove();
return S_OK;
}
public:
__property TOnMouseMove OnMouseMove = {read = FOnMouseMove, write = FOnMouseMove};
protected:
long m_cRef;
};
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TCppWebBrowser *CppWebBrowser1;
TMemo *Memo1;
TPanel *Panel1;
TEdit *Edit1;
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall CppWebBrowser1DocumentComplete(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL);
void __fastcall CppWebBrowser1NavigateComplete2(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL);
private: // User declarations
void __fastcall OnMouseMove();
_di_IDispatch CurDispatch;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//in cpp
#include <vcl.h>
#pragma hdrstop
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "SHDocVw_OCX"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
CurDispatch = NULL;
CppWebBrowser1->Navigate(WideString("http://www.codenet.ru"));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnMouseMove()
{
long cx;
long cy;
TComInterface<IHTMLDocument2> pDoc;
CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pDoc);
TComInterface<IHTMLWindow2> pWin;
TComInterface<IHTMLEventObj> pEvent;
pDoc->get_parentWindow( &pWin);
pWin->get_event( &pEvent);
if (pEvent)
{
pEvent->get_clientX( &cx);
pEvent->get_clientY( &cy);
}
String Str;
Str.printf("X = %d: Y = %d)", cx,cy);
Memo1->Lines->Add( Str);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
CppWebBrowser1->Navigate(WideString(Edit1->Text));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CppWebBrowser1DocumentComplete(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL)
{
if (pDisp == CurDispatch)
{
// the document is loaded, not just a frame
CurDispatch = NULL; //clear the global variable
IHTMLDocument2* pDoc;
CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pDoc);
THtmlEventSink* EventSink = new THtmlEventSink();
EventSink->OnMouseMove = OnMouseMove;
VARIANT vIn;
V_VT(&vIn) = VT_DISPATCH;
V_DISPATCH(&vIn) = EventSink;
// put onmousemove
if(SUCCEEDED(pDoc->put_onmousemove( vIn )))
;//ShowMessage("ConnectEvent: onmousemove");
pDoc->Release();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CppWebBrowser1NavigateComplete2(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL)
{
if (!CurDispatch)
CurDispatch = pDisp; // save for comparison
}
#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "mshtml.h"
#include "mshtmdid.h"
#include "SHDocVw_OCX.h"
#include <OleCtrls.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
typedef void __fastcall (__closure *TOnMouseMove)();
//---------------------------------------------------------------------------
class THtmlEventSink : public IDispatch
{
protected:
TOnMouseMove FOnMouseMove;
public:
THtmlEventSink() { m_cRef = 0; }
~THtmlEventSink() { /*ShowMessage("~THtmlEventSink()");*/} // trace it work
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject)
{
*ppvObject = NULL;
if (IsEqualGUID(riid, IID_IUnknown))
*ppvObject = reinterpret_cast<void**>(this);
if (IsEqualGUID(riid, IID_IDispatch))
*ppvObject = reinterpret_cast<void**>(this);
if (*ppvObject)
{
((IUnknown*)*ppvObject)->AddRef();
return S_OK;
}
else return E_NOINTERFACE;
}
DWORD __stdcall AddRef()
{
return InterlockedIncrement(&m_cRef);
}
DWORD __stdcall Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo)
{ return E_NOTIMPL; }
STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo)
{ return E_NOTIMPL; }
STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId)
{ return S_OK; }
STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO * pExcepInfo, UINT * puArgErr)
{
if (FOnMouseMove != NULL)
FOnMouseMove();
return S_OK;
}
public:
__property TOnMouseMove OnMouseMove = {read = FOnMouseMove, write = FOnMouseMove};
protected:
long m_cRef;
};
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TCppWebBrowser *CppWebBrowser1;
TMemo *Memo1;
TPanel *Panel1;
TEdit *Edit1;
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall CppWebBrowser1DocumentComplete(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL);
void __fastcall CppWebBrowser1NavigateComplete2(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL);
private: // User declarations
void __fastcall OnMouseMove();
_di_IDispatch CurDispatch;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//in cpp
#include <vcl.h>
#pragma hdrstop
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "SHDocVw_OCX"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
CurDispatch = NULL;
CppWebBrowser1->Navigate(WideString("http://www.codenet.ru"));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnMouseMove()
{
long cx;
long cy;
TComInterface<IHTMLDocument2> pDoc;
CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pDoc);
TComInterface<IHTMLWindow2> pWin;
TComInterface<IHTMLEventObj> pEvent;
pDoc->get_parentWindow( &pWin);
pWin->get_event( &pEvent);
if (pEvent)
{
pEvent->get_clientX( &cx);
pEvent->get_clientY( &cy);
}
String Str;
Str.printf("X = %d: Y = %d)", cx,cy);
Memo1->Lines->Add( Str);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
CppWebBrowser1->Navigate(WideString(Edit1->Text));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CppWebBrowser1DocumentComplete(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL)
{
if (pDisp == CurDispatch)
{
// the document is loaded, not just a frame
CurDispatch = NULL; //clear the global variable
IHTMLDocument2* pDoc;
CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pDoc);
THtmlEventSink* EventSink = new THtmlEventSink();
EventSink->OnMouseMove = OnMouseMove;
VARIANT vIn;
V_VT(&vIn) = VT_DISPATCH;
V_DISPATCH(&vIn) = EventSink;
// put onmousemove
if(SUCCEEDED(pDoc->put_onmousemove( vIn )))
;//ShowMessage("ConnectEvent: onmousemove");
pDoc->Release();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CppWebBrowser1NavigateComplete2(TObject *Sender,
LPDISPATCH pDisp, TVariant *URL)
{
if (!CurDispatch)
CurDispatch = pDisp; // save for comparison
}
================================================
Автор ответа: GIZMO
===============================================
10. E2015 Ambiguity between 'function1' and 'function2'. Подскажите что ему надо?
Ответ ================================================
Конфликт между пространствами имен. Надо четко указать - из какого пространства имен ты вызываешь функцию.
================================================
Автор ответа: kot_
===============================================
Вопрос ================================================
11. Какой компонент, наподобии OpenDialog, нужно использовать, чтобы просто выбрать путь к папке, а не к файлу?
Ответ ================================================
11.1 Вариант 1
Код:
#include <FileCtrl.hpp>
...
AnsiString Directory;
SelectDirectory("Select directory",WideString(""),Directory);
...
AnsiString Directory;
SelectDirectory("Select directory",WideString(""),Directory);
11.2 Вариант 2
Код:
char Path[255];
BROWSEINFO lpbi;
ITEMIDLIST *Id;
lpbi.hwndOwner = Handle;
lpbi.pidlRoot = NULL;
lpbi.pszDisplayName = Path;
lpbi.lpszTitle = "Каталог-источник";
lpbi.ulFlags = NULL; //BIF_BROWSEFORCOMPUTER;
lpbi.lpfn = NULL;
lpbi.lParam = NULL;
lpbi.iImage = NULL;
Id = SHBrowseForFolder(&lpbi);
if(Id)
{
SHGetPathFromIDList(Id, Path);
SourcePathEd->Text = Path;
}
BROWSEINFO lpbi;
ITEMIDLIST *Id;
lpbi.hwndOwner = Handle;
lpbi.pidlRoot = NULL;
lpbi.pszDisplayName = Path;
lpbi.lpszTitle = "Каталог-источник";
lpbi.ulFlags = NULL; //BIF_BROWSEFORCOMPUTER;
lpbi.lpfn = NULL;
lpbi.lParam = NULL;
lpbi.iImage = NULL;
Id = SHBrowseForFolder(&lpbi);
if(Id)
{
SHGetPathFromIDList(Id, Path);
SourcePathEd->Text = Path;
}
================================================
Авторы ответа: 1 - kot_, 2 - Relax
===============================================
Вопрос ================================================
12. Подскажите плиз как в Билдере разбить строку на массив символов по определенному разделителю?
Ответ ================================================
12.1 Вариант 1.
Код:
TStringList *slTabs = new TStringList;
slTabs->Delimiter = '\t';
slTabs->Clear();
slTabs->DelimitedText="Мама\tбила\tМашу";
AnsiString x1 = slTabs->Strings[0]; // Мама
AnsiString x2 = slTabs->Strings[1]; // била
AnsiString x3 = slTabs->Strings[2]; // Машу
delete slTabs;
slTabs->Delimiter = '\t';
slTabs->Clear();
slTabs->DelimitedText="Мама\tбила\tМашу";
AnsiString x1 = slTabs->Strings[0]; // Мама
AnsiString x2 = slTabs->Strings[1]; // била
AnsiString x3 = slTabs->Strings[2]; // Машу
delete slTabs;
12.2 Вариант 2.
Код:
#include <stdio.h>
#include <string.h>
int MySplit(char *src, char **dst, char splitchar);
int main(void)
{
char x[] = "Run\tLive\tTo\tFly\t,\tFly\tTo\tLive\tAces\tHigh\t!";
char *strings[60];
int i;
int n;
for(i = 0; i < 60; i++)
strings = new char[100];
n = MySplit(x, (char**)strings, '\t');
for(i = 0; i < n; i++)
puts(strings);
for(i = 0; i < 60; i++)
delete[] strings;
return 0;
}
int MySplit(char *src, char **dst, char splitchar)
{
int i;
int l;
int j;
int k;
for(k = 0, i = 0, j = 0, l = strlen(src); i < l; i++)
{
if(src == splitchar)
{
dst[j++][k] = '\0';
k = 0;
}
else
dst[j][k++] = src;
}
if(k)
dst[j][k] = '\0';
return ++j;
}
#include <string.h>
int MySplit(char *src, char **dst, char splitchar);
int main(void)
{
char x[] = "Run\tLive\tTo\tFly\t,\tFly\tTo\tLive\tAces\tHigh\t!";
char *strings[60];
int i;
int n;
for(i = 0; i < 60; i++)
strings = new char[100];
n = MySplit(x, (char**)strings, '\t');
for(i = 0; i < n; i++)
puts(strings);
for(i = 0; i < 60; i++)
delete[] strings;
return 0;
}
int MySplit(char *src, char **dst, char splitchar)
{
int i;
int l;
int j;
int k;
for(k = 0, i = 0, j = 0, l = strlen(src); i < l; i++)
{
if(src == splitchar)
{
dst[j++][k] = '\0';
k = 0;
}
else
dst[j][k++] = src;
}
if(k)
dst[j][k] = '\0';
return ++j;
}
================================================
Автор ответа: Plisteron
===============================================
Вопрос ================================================
13. Как убрать программу из TaskBarа?
Ответ ================================================
Код:
#pragma hdrstop
#include <windows.h>
#include <shlobj.h>
void StatusOnTaskBar(HWND hwnd,int status)
{
HRESULT hrc,hr;
ITaskbarList *pITaskbarList;
CoInitialize(NULL);
hrc = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER,
IID_ITaskbarList, (void**)&pITaskbarList);
if(hrc !=S_OK){MessageBox(NULL,"NoCreate","ITaskbarList",MB_OK);return;}
hr=pITaskbarList->HrInit();
if(hr ==NOERROR)
{
switch(status)
{
case 0: pITaskbarList->DeleteTab(hwnd); break;
case 1: pITaskbarList->AddTab(hwnd); break;
case 2: pITaskbarList->ActivateTab(hwnd); break;
case 3: pITaskbarList->SetActiveAlt(hwnd); break;
}
}
pITaskbarList->Release();
CoUninitialize();
}
//main.cpp
//---------------------------------------------------------------------------
#define NO_WIN32_LEAN_AND_MEAN
#include <vcl.h>
#pragma hdrstop
#include "TastTestMain.h"
#include "TaskStatus.cpp"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
StatusOnTaskBar(Application->Handle,true);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
StatusOnTaskBar(Application->Handle,false);
}
//---------------------------------------------------------------------------
#include <windows.h>
#include <shlobj.h>
void StatusOnTaskBar(HWND hwnd,int status)
{
HRESULT hrc,hr;
ITaskbarList *pITaskbarList;
CoInitialize(NULL);
hrc = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER,
IID_ITaskbarList, (void**)&pITaskbarList);
if(hrc !=S_OK){MessageBox(NULL,"NoCreate","ITaskbarList",MB_OK);return;}
hr=pITaskbarList->HrInit();
if(hr ==NOERROR)
{
switch(status)
{
case 0: pITaskbarList->DeleteTab(hwnd); break;
case 1: pITaskbarList->AddTab(hwnd); break;
case 2: pITaskbarList->ActivateTab(hwnd); break;
case 3: pITaskbarList->SetActiveAlt(hwnd); break;
}
}
pITaskbarList->Release();
CoUninitialize();
}
//main.cpp
//---------------------------------------------------------------------------
#define NO_WIN32_LEAN_AND_MEAN
#include <vcl.h>
#pragma hdrstop
#include "TastTestMain.h"
#include "TaskStatus.cpp"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
StatusOnTaskBar(Application->Handle,true);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
StatusOnTaskBar(Application->Handle,false);
}
//---------------------------------------------------------------------------
================================================
Автор ответа: SABROG
===============================================
14. Как сделать втопленную кнопку без дополнительных компонентов как
через Windows API (свойство WS_BORDER) ?
Ответ ================================================
Данный код делает все кнопки класса TButton на текущей форме втопленными.
Код:
DoubleBuffered = true;
for (int i=0; i < ControlCount;i++) {
if (AnsiString(Controls->ClassName())=="TButton"){
Controls->ControlStyle << csFramed;
}
}
Repaint();
for (int i=0; i < ControlCount;i++) {
if (AnsiString(Controls->ClassName())=="TButton"){
Controls->ControlStyle << csFramed;
}
}
Repaint();
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
15. Как обрабатывать сообщения окна (WM_*) ?
Ответ ================================================
15.1 Вариант один
Это можно сделать так:
//unit1.h
Код:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
protected: virtual void __fastcall WndProc(Messages::TMessage&); // переопределяем стандартный метод WndProc на свой - виртуальный
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
protected: virtual void __fastcall WndProc(Messages::TMessage&); // переопределяем стандартный метод WndProc на свой - виртуальный
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//unit1.cpp
Код:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WndProc(TMessage&msg)
{
switch (msg.Msg)
{
case WM_CLOSE: // реакция на закрытие формы
MessageBox(0,"Exit program",0,MB_OK);
}
TForm::WndProc(msg); // вызываем стандартный метод
}
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WndProc(TMessage&msg)
{
switch (msg.Msg)
{
case WM_CLOSE: // реакция на закрытие формы
MessageBox(0,"Exit program",0,MB_OK);
}
TForm::WndProc(msg); // вызываем стандартный метод
}
15.2 Вариант 2
Еще один вариант (при таком методе, ловятся не все сообщения):
Код:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
void __fastcall AppMessage(tagMSG &Msg, bool &Handled); // определяем функцию, которая будет ловить сообщения
};
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
void __fastcall AppMessage(tagMSG &Msg, bool &Handled); // определяем функцию, которая будет ловить сообщения
};
Код:
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Application->OnMessage = AppMessage; // переопределяем функцию, которая будет ловить сообщения
}
: TForm(Owner)
{
Application->OnMessage = AppMessage; // переопределяем функцию, которая будет ловить сообщения
}
Код:
const WM_FILEREADY = WM_USER + 2000;
void __fastcall TForm1::AppMessage(tagMSG &Msg, bool &Handled)
{
if (Msg.message == WM_FILEREADY)
{
Memo1->Lines->LoadFromFile(AnsiString((char *)Msg.lParam));
Handled = true; // не отправлять дальше по-цепочке (обработано)
}
}
void __fastcall TForm1::AppMessage(tagMSG &Msg, bool &Handled)
{
if (Msg.message == WM_FILEREADY)
{
Memo1->Lines->LoadFromFile(AnsiString((char *)Msg.lParam));
Handled = true; // не отправлять дальше по-цепочке (обработано)
}
}
================================================
Автор ответа: SABROG
================================================
16. При компиляции проекта я получаю сообщение линковщика "Unresolved external" с именем функции и указанием модуля. Как решить проблему?
Ответ ================================================
Данная ошибка говорит о том, что линковщик нашел объявление функции и функция используется в программе, но отсутствует модуль в котором эта функция реализована. Что бы устранить ошибку необходимо:
1. Ознакомиться в MSDN(http://msdn.microsoft.com) или в разделе справки билдера Windows SDK (Help\Windows SDK) с описанием функции. В конце описания как правило указывается из какого .lib файла данная функция экспортируется.
2. Зайти в папку $(BCB)\lib\psdk и найти необходимый файл.
3. Если файл найден - через Project\Add to project (или Shift+F11) добавить его в проект. Запустить компиляцию, ошибка исчезнет. Иначе следующий шаг.
4. Найдите .dll с таким же названием в системной папке.
5. Скопируйте в папку проекта.
6. Выполните утилиту $(BCB)\Bin\coff2omf c параметрами командной строки вида coff2omf dllname.dll dllnamebcb.dll
7. С получившимся файлом используйте утилиту $(BCB)\Bin\implib.exe, т.е.
implib dllnamebcb.dll dllnamebcb.lib
8. Полученую библиотеку прилинкуйте к проекту как в шаге третьем.
Кстати, я предпочитаю создавать либы а не использовать борландовские.
================================================
Автор ответа: SABROG, kot_, C++Biulder Programmer Guide
================================================
Вопрос ===============================================
17. Как можно подключить dll не используя .lib (Вариант - как подключить динамически библиотеку)? Нужно ли ее приводить к типу omf?
Ответ ================================================
Подключение библиотеки происходит при помощи LoadLibrary, вызов функции - GetProcAddress. Для этого необходимо:
1. Объявить тип указателя на функцию. Например,
Код:
typedef BOOL (__stdcall *pInternetNextFile) (HINTERNET,LPVOID);
так можно объявить указатель на функцию InternetNextFile из библиотеки WinInet
2. Обявить указатель на функцию:
Код:
pInternetNextFile InternetNextFile;
3. Объявить идентификатор модуля и загрузить его:
Код:
HINSTANCE hDll = LoadLibrary("wininet.dll");
4. Получить адрес функции
Код:
InternetNextFile = (pInternetNextFile)GetProcAddress(hInetInstance,"InternetFindNextFileA");
5. После этого - если указатель на функцию не равен нулл функцию можно вызывать как обычно.
6. По завершении работы библиотека освобождается при помощи FreeLibrary и указатели обнуляются.
При этом способе нет необходимости конвертировать библиотеку и подключать заголовочный файл.
Недостатки - дополнительные накладные расходы на загрузку функции.
================================================
Автор ответа: kot_, C++Biulder Programmer Guide et all
================================================
18. Как экспортировать класс, форму или фрейм из DLL?
Ответ ================================================
Приложение и DLL обязательно надо компилировать с пакетами времени выполнения, чтобы код классов не дублировался. Тема уже обсуждалась: тут, тут, тут и тут.
================================================
Автор ответа:Freeman
================================================
19. Как програмно прокрутить окно Memo на последнюю строку?
Ответ ================================================
Код:
Memo1->Perform(EM_LINESCROLL,0,Memo1->Lines->Count);
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
20. Как создать Edit для ввода IP адреса, как в свойствах протокола TCP/IP ?
Ответ ================================================
Код:
INITCOMMONCONTROLSEX CommCtrl;
CommCtrl.dwSize=sizeof(CommCtrl);
CommCtrl.dwICC=ICC_INTERNET_CLASSES;
if(::InitCommonControlsEx(&CommCtrl)){
HWND hWndIP=::CreateWindow("SysIPAddress32","IPAddr",\
WS_CHILD | WS_TABSTOP | WS_GROUP,10,72,130,24,Handle,0,0,0);
if (hWndIP) ::ShowWindow(hWndIP, SW_SHOW);
}
CommCtrl.dwSize=sizeof(CommCtrl);
CommCtrl.dwICC=ICC_INTERNET_CLASSES;
if(::InitCommonControlsEx(&CommCtrl)){
HWND hWndIP=::CreateWindow("SysIPAddress32","IPAddr",\
WS_CHILD | WS_TABSTOP | WS_GROUP,10,72,130,24,Handle,0,0,0);
if (hWndIP) ::ShowWindow(hWndIP, SW_SHOW);
}
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
21. Как програмно выровнять колонки у ListView (vsReport) ?
Ответ ================================================
Код:
::SendMessage(ListView1->Handle,\
LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE_USEHEADER);
LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE_USEHEADER);
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
22. Как добавить горизонтальный ScrollBar в ListBox / CheckListBox ?
Ответ ================================================
Код:
int Width, MaxWidth=0;
for (int i=0;i < ListBox1->Items->Count;i++){
Width = ListBox1->Canvas->TextWidth(ListBox1->Items->Strings+"x");
if (MaxWidth < Width) MaxWidth = Width;
}
SendMessage(ListBox1->Handle, LB_SETHORIZONTALEXTENT, MaxWidth, 0);
for (int i=0;i < ListBox1->Items->Count;i++){
Width = ListBox1->Canvas->TextWidth(ListBox1->Items->Strings+"x");
if (MaxWidth < Width) MaxWidth = Width;
}
SendMessage(ListBox1->Handle, LB_SETHORIZONTALEXTENT, MaxWidth, 0);
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
23. Как проще всего отловить нажатие горячей клавиши,
если окно программы не активно ?
Ответ ================================================
Для разного рода перехвата событий обычно
используется функция SetWindowsHookEx. Но чтобы использовать
этот метод обычно приходится писать отдельную dll. Но есть
более простой способ, который используется в множесте trainer'ов
для игр - GetAsyncKeyState. Предположим у нас есть программа,
которая висит в трее (SystemTray) или окно которой просто свернуто,
и нам нужно, чтобы она выполняла определенные действия на нажатие
клавишы. Скажем всплывать из трея и показывать себя во всей красе.
Или сделать запрос на Weather.com и показать в трее погоду в Москве.
Ну или открыть подставку для утреннего кофе ;)
Кинем на форму TTimer. Установим интервал на 500 мс. В обработчике
события пропишем действие на нажатие клавиши ScrollLock.
Код:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
WORD dwstate;
dwstate = ::GetAsyncKeyState(VK_SCROLL);
if(LOBYTE(dwstate) || HIBYTE(dwstate))
mciSendString("Set CDAudio Door Open Wait",0,0,0);
}
{
WORD dwstate;
dwstate = ::GetAsyncKeyState(VK_SCROLL);
if(LOBYTE(dwstate) || HIBYTE(dwstate))
mciSendString("Set CDAudio Door Open Wait",0,0,0);
}
Не забудьте подключить заголовок #include "mmsystem.h"
если хотите протестировать с открытием CDRom'a
================================================
Автор ответа: SABROG
================================================
19. Как програмно прокрутить окно Memo на последнюю строку?
Ответ ================================================
Код:
Memo1->Perform(EM_LINESCROLL,0,Memo1->Lines->Count);
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
20. Как создать Edit для ввода IP адреса, как в свойствах протокола TCP/IP ?
Ответ ================================================
Код:
INITCOMMONCONTROLSEX CommCtrl;
CommCtrl.dwSize=sizeof(CommCtrl);
CommCtrl.dwICC=ICC_INTERNET_CLASSES;
if(::InitCommonControlsEx(&CommCtrl)){
HWND hWndIP=::CreateWindow("SysIPAddress32","IPAddr",\
WS_CHILD | WS_TABSTOP | WS_GROUP,10,72,130,24,Handle,0,0,0);
if (hWndIP) ::ShowWindow(hWndIP, SW_SHOW);
}
CommCtrl.dwSize=sizeof(CommCtrl);
CommCtrl.dwICC=ICC_INTERNET_CLASSES;
if(::InitCommonControlsEx(&CommCtrl)){
HWND hWndIP=::CreateWindow("SysIPAddress32","IPAddr",\
WS_CHILD | WS_TABSTOP | WS_GROUP,10,72,130,24,Handle,0,0,0);
if (hWndIP) ::ShowWindow(hWndIP, SW_SHOW);
}
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
21. Как програмно выровнять колонки у ListView (vsReport) ?
Ответ ================================================
Код:
::SendMessage(ListView1->Handle,\
LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE_USEHEADER);
LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE_USEHEADER);
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
22. Как добавить горизонтальный ScrollBar в ListBox / CheckListBox ?
Ответ ================================================
Код:
int Width, MaxWidth=0;
for (int i=0;i < ListBox1->Items->Count;i++){
Width = ListBox1->Canvas->TextWidth(ListBox1->Items->Strings+"x");
if (MaxWidth < Width) MaxWidth = Width;
}
SendMessage(ListBox1->Handle, LB_SETHORIZONTALEXTENT, MaxWidth, 0);
for (int i=0;i < ListBox1->Items->Count;i++){
Width = ListBox1->Canvas->TextWidth(ListBox1->Items->Strings+"x");
if (MaxWidth < Width) MaxWidth = Width;
}
SendMessage(ListBox1->Handle, LB_SETHORIZONTALEXTENT, MaxWidth, 0);
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
23. Как проще всего отловить нажатие горячей клавиши,
если окно программы не активно ?
Ответ ================================================
Для разного рода перехвата событий обычно
используется функция SetWindowsHookEx. Но чтобы использовать
этот метод обычно приходится писать отдельную dll. Но есть
более простой способ, который используется в множесте trainer'ов
для игр - GetAsyncKeyState. Предположим у нас есть программа,
которая висит в трее (SystemTray) или окно которой просто свернуто,
и нам нужно, чтобы она выполняла определенные действия на нажатие
клавишы. Скажем всплывать из трея и показывать себя во всей красе.
Или сделать запрос на Weather.com и показать в трее погоду в Москве.
Ну или открыть подставку для утреннего кофе ;)
Кинем на форму TTimer. Установим интервал на 500 мс. В обработчике
события пропишем действие на нажатие клавиши ScrollLock.
Код:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
WORD dwstate;
dwstate = ::GetAsyncKeyState(VK_SCROLL);
if(LOBYTE(dwstate) || HIBYTE(dwstate))
mciSendString("Set CDAudio Door Open Wait",0,0,0);
}
{
WORD dwstate;
dwstate = ::GetAsyncKeyState(VK_SCROLL);
if(LOBYTE(dwstate) || HIBYTE(dwstate))
mciSendString("Set CDAudio Door Open Wait",0,0,0);
}
Не забудьте подключить заголовок #include "mmsystem.h"
если хотите протестировать с открытием CDRom'a
================================================
Автор ответа: SABROG
================================================
Вопрос ===============================================
24. Как выделить строку в StringGrid?
Ответ ================================================
Код:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Grids.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TStringGrid *StringGrid1;
void __fastcall StringGrid1DrawCell(TObject *Sender, int ACol,
int ARow, TRect &Rect, TGridDrawState State);
void __fastcall StringGrid1Click(TObject *Sender);
private: // User declarations
int oldRow, newRow;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
int I, J, K;
K = 0;
for (I = 0; I < StringGrid1->ColCount; I++)
for (J = 0; J < StringGrid1->RowCount; J++)
StringGrid1->Cells[J] = IntToStr(++K);
oldRow = 1; currRow = 1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
int ARow, TRect &Rect, TGridDrawState State)
{
if (State.Contains(gdFixed))
{
StringGrid1->Canvas->Brush->Color = clBtnFace;
StringGrid1->Canvas->Font->Color = clWindowText;
StringGrid1->Canvas->FillRect(Rect);
Frame3D(StringGrid1->Canvas, Rect, clBtnHighlight, clBtnShadow, 1);
}
else if (State.Contains(gdSelected) && ARow == newRow)
{
StringGrid1->Canvas->Brush->Color = clAqua;
StringGrid1->Canvas->Font->Color = clBlack;
StringGrid1->Canvas->FillRect(Rect);
}
else if (ARow == newRow)
{
StringGrid1->Canvas->Brush->Color = clInfoBk;
StringGrid1->Canvas->Font->Color = clBlue;
StringGrid1->Canvas->FillRect(Rect);
}
else
{
StringGrid1->Canvas->Brush->Color = StringGrid1->Color;
StringGrid1->Canvas->Font->Color = StringGrid1->Font->Color;
StringGrid1->Canvas->FillRect(Rect);
}
StringGrid1->Canvas->TextRect(
Rect, Rect.Left, Rect.Top, StringGrid1->Cells[ACol][ARow]
);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StringGrid1Click(TObject *Sender)
{
if(oldRow == StringGrid1->Row) return;
RECT R1, R2, R3;
newRow = StringGrid1->Row;
int ViewCol = ((StringGrid1->VisibleColCount + StringGrid1->LeftCol) < StringGrid1->ColCount) ? StringGrid1->LeftCol + StringGrid1->VisibleColCount : StringGrid1->ColCount - 1;
R1 = StringGrid1->CellRect(/*StringGrid1->LeftCol*/0, oldRow);
R2 = StringGrid1->CellRect(ViewCol, oldRow);
UnionRect(&R3, &R1, &R2);
InvalidateRect(StringGrid1->Handle, &R3, false);
R1 = StringGrid1->CellRect(/*StringGrid1->LeftCol*/0, newRow);
R2 = StringGrid1->CellRect(ViewCol, newRow);
UnionRect(&R3, &R1, &R2);
InvalidateRect(StringGrid1->Handle, &R3, false);
oldRow = newRow;
}
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Grids.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TStringGrid *StringGrid1;
void __fastcall StringGrid1DrawCell(TObject *Sender, int ACol,
int ARow, TRect &Rect, TGridDrawState State);
void __fastcall StringGrid1Click(TObject *Sender);
private: // User declarations
int oldRow, newRow;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
int I, J, K;
K = 0;
for (I = 0; I < StringGrid1->ColCount; I++)
for (J = 0; J < StringGrid1->RowCount; J++)
StringGrid1->Cells[J] = IntToStr(++K);
oldRow = 1; currRow = 1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
int ARow, TRect &Rect, TGridDrawState State)
{
if (State.Contains(gdFixed))
{
StringGrid1->Canvas->Brush->Color = clBtnFace;
StringGrid1->Canvas->Font->Color = clWindowText;
StringGrid1->Canvas->FillRect(Rect);
Frame3D(StringGrid1->Canvas, Rect, clBtnHighlight, clBtnShadow, 1);
}
else if (State.Contains(gdSelected) && ARow == newRow)
{
StringGrid1->Canvas->Brush->Color = clAqua;
StringGrid1->Canvas->Font->Color = clBlack;
StringGrid1->Canvas->FillRect(Rect);
}
else if (ARow == newRow)
{
StringGrid1->Canvas->Brush->Color = clInfoBk;
StringGrid1->Canvas->Font->Color = clBlue;
StringGrid1->Canvas->FillRect(Rect);
}
else
{
StringGrid1->Canvas->Brush->Color = StringGrid1->Color;
StringGrid1->Canvas->Font->Color = StringGrid1->Font->Color;
StringGrid1->Canvas->FillRect(Rect);
}
StringGrid1->Canvas->TextRect(
Rect, Rect.Left, Rect.Top, StringGrid1->Cells[ACol][ARow]
);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StringGrid1Click(TObject *Sender)
{
if(oldRow == StringGrid1->Row) return;
RECT R1, R2, R3;
newRow = StringGrid1->Row;
int ViewCol = ((StringGrid1->VisibleColCount + StringGrid1->LeftCol) < StringGrid1->ColCount) ? StringGrid1->LeftCol + StringGrid1->VisibleColCount : StringGrid1->ColCount - 1;
R1 = StringGrid1->CellRect(/*StringGrid1->LeftCol*/0, oldRow);
R2 = StringGrid1->CellRect(ViewCol, oldRow);
UnionRect(&R3, &R1, &R2);
InvalidateRect(StringGrid1->Handle, &R3, false);
R1 = StringGrid1->CellRect(/*StringGrid1->LeftCol*/0, newRow);
R2 = StringGrid1->CellRect(ViewCol, newRow);
UnionRect(&R3, &R1, &R2);
InvalidateRect(StringGrid1->Handle, &R3, false);
oldRow = newRow;
}
//---------------------------------------------------------------------------
================================================
Автор ответа: GIZMO
================================================
25. Как удалить строку/столбец в StrinGrid?
Ответ ================================================
Удалить в компоненте TStringGrid произвольную строку или столбец нельзя, только последнюю(ий) и поэтому получается следующее...
Код:
//удалить колонку...
void RemoveCol(TStringGrid* StringGrid, int Index)
{
assert(StringGrid != NULL);
//откл. перерисовку...
SNDMSG(StringGrid->Handle, WM_SETREDRAW, false, 0);
try
{
const int col_count = StringGrid->ColCount;
// смещаем стобцы на один влево
for (int col = Index; col < col_count - 1; ++col)
{
StringGrid->Cols[col] = StringGrid->Cols[col + 1];
}
// удаляем последнюю колонку...
StringGrid->ColCount = col_count -1;
}
__finally
{
SNDMSG(StringGrid->Handle, WM_SETREDRAW, true, 0);
}
// вычисляем область для перерисовки...
RECT R = StringGrid->CellRect(0, Index);
InflateRect(&R, StringGrid->Width, StringGrid->Height);
//и обновляем ее...
InvalidateRect(StringGrid->Handle, &R, false);
}
//-----------------------------------------------------------------------------
void RemoveCol(TStringGrid* StringGrid, int Index)
{
assert(StringGrid != NULL);
//откл. перерисовку...
SNDMSG(StringGrid->Handle, WM_SETREDRAW, false, 0);
try
{
const int col_count = StringGrid->ColCount;
// смещаем стобцы на один влево
for (int col = Index; col < col_count - 1; ++col)
{
StringGrid->Cols[col] = StringGrid->Cols[col + 1];
}
// удаляем последнюю колонку...
StringGrid->ColCount = col_count -1;
}
__finally
{
SNDMSG(StringGrid->Handle, WM_SETREDRAW, true, 0);
}
// вычисляем область для перерисовки...
RECT R = StringGrid->CellRect(0, Index);
InflateRect(&R, StringGrid->Width, StringGrid->Height);
//и обновляем ее...
InvalidateRect(StringGrid->Handle, &R, false);
}
//-----------------------------------------------------------------------------
Тоже самое со строками.
================================================
Автор ответа: GIZMO
================================================
25. Как удалить строку/столбец в StrinGrid?
Ответ ================================================
Удалить в компоненте TStringGrid произвольную строку или столбец нельзя, только последнюю(ий) и поэтому получается следующее...
Код:
//удалить колонку...
void RemoveCol(TStringGrid* StringGrid, int Index)
{
assert(StringGrid != NULL);
//откл. перерисовку...
SNDMSG(StringGrid->Handle, WM_SETREDRAW, false, 0);
try
{
const int col_count = StringGrid->ColCount;
// смещаем стобцы на один влево
for (int col = Index; col < col_count - 1; ++col)
{
StringGrid->Cols[col] = StringGrid->Cols[col + 1];
}
// удаляем последнюю колонку...
StringGrid->ColCount = col_count -1;
}
__finally
{
SNDMSG(StringGrid->Handle, WM_SETREDRAW, true, 0);
}
// вычисляем область для перерисовки...
RECT R = StringGrid->CellRect(0, Index);
InflateRect(&R, StringGrid->Width, StringGrid->Height);
//и обновляем ее...
InvalidateRect(StringGrid->Handle, &R, false);
}
//-----------------------------------------------------------------------------
void RemoveCol(TStringGrid* StringGrid, int Index)
{
assert(StringGrid != NULL);
//откл. перерисовку...
SNDMSG(StringGrid->Handle, WM_SETREDRAW, false, 0);
try
{
const int col_count = StringGrid->ColCount;
// смещаем стобцы на один влево
for (int col = Index; col < col_count - 1; ++col)
{
StringGrid->Cols[col] = StringGrid->Cols[col + 1];
}
// удаляем последнюю колонку...
StringGrid->ColCount = col_count -1;
}
__finally
{
SNDMSG(StringGrid->Handle, WM_SETREDRAW, true, 0);
}
// вычисляем область для перерисовки...
RECT R = StringGrid->CellRect(0, Index);
InflateRect(&R, StringGrid->Width, StringGrid->Height);
//и обновляем ее...
InvalidateRect(StringGrid->Handle, &R, false);
}
//-----------------------------------------------------------------------------
Тоже самое со строками.
================================================
Автор ответа: GIZMO
================================================
Вопрос ===============================================
26. Как в компонент TWebBrowser загрузить HTML код из строки?
Ответ ================================================
Например так:
Код:
TStringStream *str = new TStringStream("");
str->WriteString("<html>\n");
str->WriteString("<head><title>");
str->WriteString("Заголовок");
str->WriteString("</title></head>\n");
str->WriteString("<body>\n");
str->WriteString("<table border=\"1\" cellpadding=\"5\"cellspacing=\"0\">\n");
str->WriteString(" <tr>\n");
str->WriteString(" <td>\n");
str->WriteString(" ");
str->WriteString(String("Значение 1") + "\n");
str->WriteString(" </td>\n");
str->WriteString(" </tr>\n");
str->WriteString(" <tr>\n");
str->WriteString(" <td>\n");
str->WriteString(" ");
str->WriteString(String("Значение 2") + "\n");
str->WriteString(" </td>\n");
str->WriteString(" </tr>\n");
str->WriteString("</table>");
str->WriteString("</body>\n");
str->WriteString("</html>");
LPDISPATCH DocDispatch = WB->ControlInterface->get_Document();
if (!DocDispatch)
{
return;
}
IHTMLDocument2 *docInterface;
HRESULT hr = S_OK;
hr = DocDispatch->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&docInterface);
if (!SUCCEEDED(hr))
{
return;
}
VARIANT *param;
SAFEARRAY *sfArray;
sfArray = SafeArrayCreateVector(VT_VARIANT, 0, 1);
if (sfArray)
{
SafeArrayAccessData(sfArray, (LPVOID*) ¶m);
param->vt = VT_BSTR;
param->bstrVal = WideString(str->DataString);
SafeArrayUnaccessData(sfArray);
docInterface->write(sfArray);
SafeArrayDestroy(sfArray);
}
delete str;
str->WriteString("<html>\n");
str->WriteString("<head><title>");
str->WriteString("Заголовок");
str->WriteString("</title></head>\n");
str->WriteString("<body>\n");
str->WriteString("<table border=\"1\" cellpadding=\"5\"cellspacing=\"0\">\n");
str->WriteString(" <tr>\n");
str->WriteString(" <td>\n");
str->WriteString(" ");
str->WriteString(String("Значение 1") + "\n");
str->WriteString(" </td>\n");
str->WriteString(" </tr>\n");
str->WriteString(" <tr>\n");
str->WriteString(" <td>\n");
str->WriteString(" ");
str->WriteString(String("Значение 2") + "\n");
str->WriteString(" </td>\n");
str->WriteString(" </tr>\n");
str->WriteString("</table>");
str->WriteString("</body>\n");
str->WriteString("</html>");
LPDISPATCH DocDispatch = WB->ControlInterface->get_Document();
if (!DocDispatch)
{
return;
}
IHTMLDocument2 *docInterface;
HRESULT hr = S_OK;
hr = DocDispatch->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&docInterface);
if (!SUCCEEDED(hr))
{
return;
}
VARIANT *param;
SAFEARRAY *sfArray;
sfArray = SafeArrayCreateVector(VT_VARIANT, 0, 1);
if (sfArray)
{
SafeArrayAccessData(sfArray, (LPVOID*) ¶m);
param->vt = VT_BSTR;
param->bstrVal = WideString(str->DataString);
SafeArrayUnaccessData(sfArray);
docInterface->write(sfArray);
SafeArrayDestroy(sfArray);
}
delete str;
================================================
Автор ответа: GIZMO
================================================
27. Как научить DBGrid слушаться колесико мышки?
Ответ ================================================
Вариантов несколько - можно повесить обработчик на событие OnMessage глобального объекта TApplication, ловить событие WM_MOUSEWHEEL и если оно пришло от DBGrid менять тип (на WM_KEYDOWN) и параметры (на VK_UP | VK_DOWN).
Можно сабкласить оконную процедуру DBGrid непосредственно.
Код:
// in hpp
TWndMethod oldDBGridProc;
void __fastcall newDBGridProc(TMessage& msg);
//void __fastcall OnApplicationMessage(TMsg& Msg, bool &Handled ); // вариант с Application->OnMessage
// in cpp
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//Application->OnMessage = OnApplicationMessage; // вариант с Application->OnMessage
oldDBGridProc = DBGrid1->WindowProc;
DBGrid1->WindowProc = newDBGridProc;
}
/*void __fastcall TForm1::OnApplicationMessage( TMsg& Msg, bool &Handled )
{
if( Msg.message == WM_MOUSEWHEEL )
{
if( dynamic_cast<TDBGrid*>(Screen->ActiveControl) )
{
short zDelta = HIWORD( Msg.wParam );
if( zDelta != 0 )
{
// изменяем тип и параметры сообщения
Msg.lParam = 0;
Msg.message = WM_KEYDOWN;
if( zDelta > 0 ) Msg.wParam = VK_UP;
else Msg.wParam = VK_DOWN;
}
}
}
}*/
void __fastcall TForm1::newDBGridProc(TMessage& msg)
{
if(msg.Msg == WM_MOUSEWHEEL) {
short zDelta = msg.WParamHi;
if( zDelta != 0 )
{
// change the message to indicate a keypress instead
msg.Result = 0;
msg.Msg = WM_KEYDOWN;
if( zDelta > 0 ) msg.WParam = VK_UP;
else msg.WParam = VK_DOWN;
}
}
oldDBGridProc(msg);
}
TWndMethod oldDBGridProc;
void __fastcall newDBGridProc(TMessage& msg);
//void __fastcall OnApplicationMessage(TMsg& Msg, bool &Handled ); // вариант с Application->OnMessage
// in cpp
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//Application->OnMessage = OnApplicationMessage; // вариант с Application->OnMessage
oldDBGridProc = DBGrid1->WindowProc;
DBGrid1->WindowProc = newDBGridProc;
}
/*void __fastcall TForm1::OnApplicationMessage( TMsg& Msg, bool &Handled )
{
if( Msg.message == WM_MOUSEWHEEL )
{
if( dynamic_cast<TDBGrid*>(Screen->ActiveControl) )
{
short zDelta = HIWORD( Msg.wParam );
if( zDelta != 0 )
{
// изменяем тип и параметры сообщения
Msg.lParam = 0;
Msg.message = WM_KEYDOWN;
if( zDelta > 0 ) Msg.wParam = VK_UP;
else Msg.wParam = VK_DOWN;
}
}
}
}*/
void __fastcall TForm1::newDBGridProc(TMessage& msg)
{
if(msg.Msg == WM_MOUSEWHEEL) {
short zDelta = msg.WParamHi;
if( zDelta != 0 )
{
// change the message to indicate a keypress instead
msg.Result = 0;
msg.Msg = WM_KEYDOWN;
if( zDelta > 0 ) msg.WParam = VK_UP;
else msg.WParam = VK_DOWN;
}
}
oldDBGridProc(msg);
}
================================================
Автор ответа: GIZMO
================================================
28. Как ограничить тип вводимых данных в компонент Edit (нужен только int)?
Ответ ================================================
Установить стиль ES_NUMBER:
Код:
SetWindowLong(Edit1->Handle, GWL_STYLE, GetWindowLong(Edit1->Handle, GWL_STYLE) | ES_NUMBER);
================================================
Автор ответа: GIZMO
================================================
Вопрос ===============================================
29. Как удалить файлы по шаблону?
Ответ ================================================
Примерно так:
Код:
include<SysUtils.hpp>
void __fastcall DeleteAllFiles(AnsiString path)
{
int iAttributes = faAnyFile;
TSearchRec sr;
AnsiString alles("*.*");
AnsiString dot(".");
AnsiString dotdot("..");
AnsiString Path(path);
AnsiString File;
if(FindFirst(IncludeTrailingBackslash(Path) + alles, iAttributes, sr) == 0)
{
do
{
File = IncludeTrailingBackslash(Path) + sr.Name;
if((sr.Attr & faDirectory) == faDirectory)
{
if(sr.Name != dot && sr.Name != dotdot)
DeleteAllFiles(File);
}
else
{
SetFileAttributes(File.c_str(), FILE_ATTRIBUTE_NORMAL);
DeleteFile(File.c_str());
}
}
while (FindNext(sr) == 0);
}
FindClose(sr);
}
void __fastcall DeleteAllFiles(AnsiString path)
{
int iAttributes = faAnyFile;
TSearchRec sr;
AnsiString alles("*.*");
AnsiString dot(".");
AnsiString dotdot("..");
AnsiString Path(path);
AnsiString File;
if(FindFirst(IncludeTrailingBackslash(Path) + alles, iAttributes, sr) == 0)
{
do
{
File = IncludeTrailingBackslash(Path) + sr.Name;
if((sr.Attr & faDirectory) == faDirectory)
{
if(sr.Name != dot && sr.Name != dotdot)
DeleteAllFiles(File);
}
else
{
SetFileAttributes(File.c_str(), FILE_ATTRIBUTE_NORMAL);
DeleteFile(File.c_str());
}
}
while (FindNext(sr) == 0);
}
FindClose(sr);
}
================================================
Автор ответа: Plisteron
================================================
Вопрос ===============================================
30. Как вызвав, почтового клиента, поместить сразу же туда автоматически текст сообщения и отправителя?
Ответ ================================================
Код:
ShellExecute(Handle,"open","mailto:mail@mail.ru?subject=\"У Шуры Шара\"&body=\"Шура шарит Шаурму\"",NULL,NULL,SW_SHOW);
================================================
Автор ответа: Plisteron
================================================
31. как программно установить BorderIcons. т.е. мне нужно убрать кнопки минимизировать и распахнуть.
Ответ======================================================
Код:
TBorderIcons tempBI = BorderIcons;
tempBI >> biMaximize;
tempBI >> biMinimize;
BorderIcons = tempBI;
tempBI >> biMaximize;
tempBI >> biMinimize;
BorderIcons = tempBI;
или
Код:
BorderStyle = bsToolWindow;
======================================================
Автор ответа: BCB Help. Разместил kot_
32. Загрузка без картинок в CppWebBroser... как?
Ответ======================================================
Здесь: http://sources.codenet.ru/download/1321/CustomDowndLoad.html
Использовать примерно так:
Код:
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
CustomDownLoad = new TCustomDownLoad(CppWebBrowser1);
N4->Checked = CustomDownLoad->DownloadControlOptions.Contains(dcoImages);
CppWebBrowser1->Navigate(WideString("http://forum.codenet.ru/reputation.php?p=179006"));
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1() {
CustomDownLoad->Release();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N4Click(TObject *Sender)
{
if(CustomDownLoad->DownloadControlOptions.Contains(dcoImages))
CustomDownLoad->DownloadControlOptions = TDownloadControlOptions();
else
CustomDownLoad->DownloadControlOptions = TDownloadControlOptions() << dcoImages;
N4->Checked = !N4->Checked;
CppWebBrowser1->Refresh();
}
: TForm(Owner)
{
CustomDownLoad = new TCustomDownLoad(CppWebBrowser1);
N4->Checked = CustomDownLoad->DownloadControlOptions.Contains(dcoImages);
CppWebBrowser1->Navigate(WideString("http://forum.codenet.ru/reputation.php?p=179006"));
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1() {
CustomDownLoad->Release();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N4Click(TObject *Sender)
{
if(CustomDownLoad->DownloadControlOptions.Contains(dcoImages))
CustomDownLoad->DownloadControlOptions = TDownloadControlOptions();
else
CustomDownLoad->DownloadControlOptions = TDownloadControlOptions() << dcoImages;
N4->Checked = !N4->Checked;
CppWebBrowser1->Refresh();
}
======================================================
Автор ответа: GIZMO
Вопрос ====================================================
33. Как программно нажать кнопку на HTML странице?
Ответ======================================================
Примерно так:
Код:
void __fastcall TForm1::ClickButtonByName(String ButtonName)
{
//TODO: Add your source code here
if( WB->Document )
{
TComInterface<IHTMLDocument2> pDocument;
WB->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pDocument);
if( pDocument )
{
TComInterface<IHTMLElementCollection> pCollection;
pDocument->get_all(&pCollection);
if( pCollection )
{
TComInterface<IDispatch> pDisp;
pCollection->item(TVariant(WideString(ButtonName)), TVariant(0), &pDisp);
if( pDisp )
{
TComInterface<IHTMLElement> pElement;
pDisp->QueryInterface(IID_IHTMLElement, (LPVOID*)&pElement);
if( pElement )
{
pElement->click();
}
}
}
}
}
}
{
//TODO: Add your source code here
if( WB->Document )
{
TComInterface<IHTMLDocument2> pDocument;
WB->Document->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pDocument);
if( pDocument )
{
TComInterface<IHTMLElementCollection> pCollection;
pDocument->get_all(&pCollection);
if( pCollection )
{
TComInterface<IDispatch> pDisp;
pCollection->item(TVariant(WideString(ButtonName)), TVariant(0), &pDisp);
if( pDisp )
{
TComInterface<IHTMLElement> pElement;
pDisp->QueryInterface(IID_IHTMLElement, (LPVOID*)&pElement);
if( pElement )
{
pElement->click();
}
}
}
}
}
}
======================================================
Автор ответа: автоответчик:)
8. Как ускорить вывод/загрузку данных в/из Excel? (обновлено)
Ответ ================================================
...
8.3 Вариант 3. Работа через АДО.
Код:
ADOQuery1->ConnectionString = WideString("Provider=MSDASQL.1;Persist Security Info=False;Extended Properties="DSN=Excel Files;DBQ=D:\\ArchiveAccessBase\\Tvoy_file.xls;DefaultDir=D:\\ArchiveAccessBase;DriverId=790;MaxBufferSize=2048;PageTimeout=5;";Initial Catalog=D:\\ArchiveAccessBase\\Tvoy_file");
ADOQuery1->SQL->Clear();
ADOQuery1->SQL->Add("Select * from [Sheet1$]");
ADOQuery1->Active = true;
while(!ADOQuery1->Eof){
//Далее стандартная работа
...
ADOQuery1->Next();
}
ADOQuery1->SQL->Clear();
ADOQuery1->SQL->Add("Select * from [Sheet1$]");
ADOQuery1->Active = true;
while(!ADOQuery1->Eof){
//Далее стандартная работа
...
ADOQuery1->Next();
}
================================================
Автор ответа: kot_
===============================================
34. Drag and Drop файлов на форму/компоненту?
Ответ ================================================
Код:
добавляем в [Unit1.h] в секции несколько строчек
class TForm1 : public TForm
{
private: // User declarations
void virtual __fastcall WMDropFiles(TWMDropFiles &message);
public: // User declarations
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_DROPFILES,TWMDropFiles,WMDropFiles)
END_MESSAGE_MAP(TForm);
};
[Unit1.cpp]
void __fastcall TForm1::FormCreate(TObject *Sender)
{
DragAcceptFiles(Form1->Handle, true);
//вместо Form1 может быть любой компонент, например, ListBox или Memo, тогда файлы будут дропаться только над этим компонентом
//это я выяснил как раз во время написания данного поста, который изначально был вопросом, как это делать :)
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WMDropFiles(TWMDropFiles &message)
{
int filecount, length, i;
filecount = DragQueryFile ((HDROP) message.Drop, 0xFFFFFFFF/*-1*/, NULL, 0); //получаем количество файлов
//подробнее о параметрах и возвращаемых значениях DragQueryFile можно узнать тут или в хелпе Билдера
AnsiString filename;
for (i = 0; i < filecount; ++i) {
filename.SetLength(MAX_PATH);
length = DragQueryFile((HDROP)message.Drop, i, filename.c_str(), filename.Length());
filename.SetLength(length);
//тут можно с файлами творить что угодно, например, имена добавить в StringList или открывать по очереди в Memo
}
DragFinish ((HDROP) message.Drop);
}
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
private: // User declarations
void virtual __fastcall WMDropFiles(TWMDropFiles &message);
public: // User declarations
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_DROPFILES,TWMDropFiles,WMDropFiles)
END_MESSAGE_MAP(TForm);
};
[Unit1.cpp]
void __fastcall TForm1::FormCreate(TObject *Sender)
{
DragAcceptFiles(Form1->Handle, true);
//вместо Form1 может быть любой компонент, например, ListBox или Memo, тогда файлы будут дропаться только над этим компонентом
//это я выяснил как раз во время написания данного поста, который изначально был вопросом, как это делать :)
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WMDropFiles(TWMDropFiles &message)
{
int filecount, length, i;
filecount = DragQueryFile ((HDROP) message.Drop, 0xFFFFFFFF/*-1*/, NULL, 0); //получаем количество файлов
//подробнее о параметрах и возвращаемых значениях DragQueryFile можно узнать тут или в хелпе Билдера
AnsiString filename;
for (i = 0; i < filecount; ++i) {
filename.SetLength(MAX_PATH);
length = DragQueryFile((HDROP)message.Drop, i, filename.c_str(), filename.Length());
filename.SetLength(length);
//тут можно с файлами творить что угодно, например, имена добавить в StringList или открывать по очереди в Memo
}
DragFinish ((HDROP) message.Drop);
}
//---------------------------------------------------------------------------
================================================
Автор ответа: AntidotE
===============================================
35. Как работать со службами(servises)(запустить,остановить,настроить)?
Ответ ================================================
1. Шаг первый
Подключиться к менеджеру севисов(ServiceControlMenager)
Код:
SC_HANDLE hSCM = NULL;
DWORD dwAccess=SC_MANAGER_CONNECT;
hSCM = OpenSCManager(NULL /*локальная машина*/,NULL /*текущая база*/,dwAccess);
if(!hSCM){
//Обработка ошибки
return;
}
DWORD dwAccess=SC_MANAGER_CONNECT;
hSCM = OpenSCManager(NULL /*локальная машина*/,NULL /*текущая база*/,dwAccess);
if(!hSCM){
//Обработка ошибки
return;
}
флаги доступа могут быть комбинированы между собой. Существуют следующие:
- SERVICE_START - разрешено запускать сервисы
- SERVICE_STOP - разрешено останавливать сервисы
- DELETE - разрешено удалять сервисы
- SERVICE_CHANGE_CONFIG - разрешено конфигурировать сервисы
- SERVICE_ALL_ACCESS - включает полные права доступа
2. Шаг второй
Необходимо получить внутреннее имя сервиса, по внешнему имени (на примере Firebird Server):
Код:
char outName[] = "Firebird Server";
DWORD dwBuff = 256;
char *inName = new char[dwBuff];
if(!GetServiceKeyName(hSCM,outName,inName,&dwBuff){
//Обработка ошибки
return;
}
DWORD dwBuff = 256;
char *inName = new char[dwBuff];
if(!GetServiceKeyName(hSCM,outName,inName,&dwBuff){
//Обработка ошибки
return;
}
Внешнее имя можно посмотреть в консоли управлениями сервисами. Если это ваш сервис, или его внутренне имя вам известно - переходите к следующему шагу.
3. Шаг третий
Подключение к сервису.
Код:
SC_HANDLE hService = NULL;
hService = OpenService(hSCM,servName,dwAccess);
if(!hService){
//Обработка ошибки
return;
}
hService = OpenService(hSCM,servName,dwAccess);
if(!hService){
//Обработка ошибки
return;
}
Флаги доступа см. выше.
4. Шаг четвертый
Конфигурирование.
Код:
QUERY_SERVICE_CONFIG* lpQSC;
DWORD dwNeeded;
lpQSC = (
QUERY_SERVICE_CONFIG)new char[4096];
if(!QueryServiceConfig(hService,lpQSC,4096,&dwNeeded)){
//Обработка ошибки
return;
}
//Обрабатываем полученную инфу
DWORD dwNeeded;
lpQSC = (
QUERY_SERVICE_CONFIG)new char[4096];
if(!QueryServiceConfig(hService,lpQSC,4096,&dwNeeded)){
//Обработка ошибки
return;
}
//Обрабатываем полученную инфу
Изменяем конфигурацию - устанавливаем автоматический запуск
Код:
if(!ChangeServiceConfig(hService,SERVICE_NO_CHANGE,SERVICE_AUTO_START,
SERVICE_NO_CHANGE,
NULL,NULL,NULL,NULL,NULL,NULL,NULL)){
//Обработка ошибки
return;
}
SERVICE_NO_CHANGE,
NULL,NULL,NULL,NULL,NULL,NULL,NULL)){
//Обработка ошибки
return;
}
5. Шаг пятый
Остановка сервиса
Код:
SERVICE_STATUS status_service;
if(!ControlService(hService,SERVICE_CONTROL_STOP,&status_service)){
//Обработка ошибки
return;
}
if(!ControlService(hService,SERVICE_CONTROL_STOP,&status_service)){
//Обработка ошибки
return;
}
6. Шаг шестой
Закрываем все открытые хендлы и освобождаем ресурсы.
================================================
Автор ответа: kot_
===============================================
36. Как реализовать доступ к VCL объектам другой программы (внешнего процесса)?
Ответ ================================================
Некоторые компоненты не имеют HWND по определению. К ним относятся, например, TCGauge, TImage, TToolButton, а также TLabel.
Возникает вопрос: как получить доступ к свойствам таких объектов, причем находящимся в другой программе?
Итак, перед нами стоит такая задача:
1. Нажать кнопку TToolButton в другом приложении
2. Получить значение прогресса TCGauge (тоже в другом приложении)
Подход будет не через стандартные EnumChildWindow() и не через SendMessage(), так как для вызова таких функций необходимы HWND, а наши объекты его не имеют. Можно в этом убедиться, воспользовавшись программами InqSoft Window Scanner или Spy++. Также некорректно будет имитировать нажатие кнопки или клик мыши, ведь если нам необходимо скрыть приложение от глаз пользователя, то такие способы не помогут.
План действий таков: создаем DLL, который будем подключать к приложению, в котором находятся необходимые нам объекты. Когда мы подключим DLL к приложению, мы, фактически, получим доступ ко всем компонентам и контролам на форме. Таким образом, нажать TToolButton не составит труда. Чтобы получить значение TCGauge и передать его из другого приложения своему, необходимо будет создать динамический TTimer, который будет получать информацию от TCGauge и передавать нашей программе, скажем, каждую секунду.
Для начала потребуется получить таблицу экспорта приложения с необходимыми контролами. В папке BCB находится файл tdump, которым мы и воспользуемся. Запускаем его так:
1. cmd.exe
2. cd «C:\Program Files\Borland\CBuilder6\Bin\»
3. tdump «C:\MyProgramCatalog\AppToTDump.exe»
В самом низу будут выписаны ресурсы, выше - таблица экспорта. В этой таблице будут все компоненты на форме, из которых мы сможем выбрать необходимые нам. Также там будет представлена информация об операциях и функциях, которые используются в программе.
Итак, код файла DLL:
Код:
#include <windows.h>
#include <vcl.h>
#include "CGAUGES.h" // для управления TCGauge
#pragma argsused
// этими объектами можно управлять, как своими. Можно добавить сюда необходимые
TForm *MainForm = NULL;
TCGauge *CGauge1 = NULL;
//---------------------------------------------------------------------------
void Init() //Инициализация и проверка управления
{
TForm **pForm = (TForm**)GetProcAddress(GetModuleHandle(NULL), "_MainForm"); //Поиск форм и присваивание указателя
if(pForm == NULL) //Если присваивание не удалось
{
/* Ошибка! Форма не найдена */
} else
{
MainForm = *pForm;
if(MainForm == NULL)
{
/* Ошибка! Нужная форма недоступна. Например, неверное имя формы */
} else
{
CGauge1 = (TCGauge*)MainForm->FindComponent("CGauge1"); //Присваиваем указатель на TCGauge
if(CGauge1 == NULL) //Если не удалось
{
/* Ошибка! TCGauge не найден */
} else
{
CGauge1->Progress = 50; //устанавливаем значение 50, чтобы протестировать
}
}
}
}
//---------------------------------------------------------------------------
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH: //Если удалось подключить DLL
Init(); //Инициализируем тестовую проверку
break;
}
return 1;
}
//---------------------------------------------------------------------------
/*А вот пример простой программы-стартера, который подключит DLL и будет получать команды от TTimer*/
#include <vcl.h>
//---------------------------------------------------------------------------
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner){}
//---------------------------------------------------------------------------
HMODULE hRemoteModule=NULL;
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
bool bSuccess = false;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
if(!CreateProcess(NULL, "AppWithControl.exe", 0, 0, FALSE, 0, 0, 0, &si, &pi)) //Запускаем приложение с необходимыми контролами
{
ShowMessage(SysErrorMessage(GetLastError()));
} else
{
DWORD res = WaitForInputIdle(pi.hProcess, 10000); //Ставим таймер на 10 секунд
if(res == WAIT_TIMEOUT) //Если приложение не запустилось
{
if (MessageBoxA(Handle, "Превышен предел ожидания. Уничтожить процесс?", 0, MB_YESNO | 16) == IDYES)
{
TerminateProcess(pi.hProcess, 0);
}
} else
{
String DllPath = ExtractFilePath(Application->ExeName) + "ControlDLL.dll";
LPVOID p = VirtualAllocEx(pi.hProcess, 0, DllPath.Length() + 1, MEM_COMMIT, PAGE_READWRITE);
if (!p)
{
ShowMessage("Невозможно получить доступ к памяти процесса! Ошибка: " + SysErrorMessage(GetLastError()));
} else
{
if (!WriteProcessMemory(pi.hProcess, p, DllPath.c_str(), DllPath.Length() + 1, NULL))
{
ShowMessage("Невозможно получить доступ к памяти процесса!");
} else
{
FARPROC fp = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if(!fp)
{
ShowMessage("Невозможно получить адрес kernel32.dll!");
} else
{
HANDLE hThread = CreateRemoteThread(pi.hProcess, 0, 0, (LPTHREAD_START_ROUTINE)fp, (LPVOID)p, 0, NULL);
if(!hThread)
{
ShowMessage("Невозможно создать удаленный поток! Ошибка: " + SysErrorMessage(GetLastError()));
} else
{
res = WaitForSingleObject(hThread, 10000); //Ставим таймер на 10 секунд
if(res == WAIT_TIMEOUT) //Если время ожидания вышло
{
if (MessageBoxA(Handle, "Поток завис. Завершить его?", 0, 16 | MB_YESNO) == IDYES)
{
TerminateThread(hThread, 0);
}
}
GetExitCodeThread(hThread, (LPDWORD)&hRemoteModule);
if(hRemoteModule)
{
bSuccess = true;
} else
{
ShowMessage("Инициализация DLL в удалённом процессе завершена с ошибкой!");
}
CloseHandle(hThread);
}
}
}
VirtualFreeEx(pi.hProcess, p, DllPath.Length() + 1, MEM_FREE); //Освобождаем пямять
}
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
if(bSuccess) //Если все проверки прошли успешно
{
ShowMessage("Операция успешно завершена!");
}
}
//---------------------------------------------------------------------------
/****************************************************************************/
#include <vcl.h>
#include "CGAUGES.h" // для управления TCGauge
#pragma argsused
// этими объектами можно управлять, как своими. Можно добавить сюда необходимые
TForm *MainForm = NULL;
TCGauge *CGauge1 = NULL;
//---------------------------------------------------------------------------
void Init() //Инициализация и проверка управления
{
TForm **pForm = (TForm**)GetProcAddress(GetModuleHandle(NULL), "_MainForm"); //Поиск форм и присваивание указателя
if(pForm == NULL) //Если присваивание не удалось
{
/* Ошибка! Форма не найдена */
} else
{
MainForm = *pForm;
if(MainForm == NULL)
{
/* Ошибка! Нужная форма недоступна. Например, неверное имя формы */
} else
{
CGauge1 = (TCGauge*)MainForm->FindComponent("CGauge1"); //Присваиваем указатель на TCGauge
if(CGauge1 == NULL) //Если не удалось
{
/* Ошибка! TCGauge не найден */
} else
{
CGauge1->Progress = 50; //устанавливаем значение 50, чтобы протестировать
}
}
}
}
//---------------------------------------------------------------------------
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH: //Если удалось подключить DLL
Init(); //Инициализируем тестовую проверку
break;
}
return 1;
}
//---------------------------------------------------------------------------
/*А вот пример простой программы-стартера, который подключит DLL и будет получать команды от TTimer*/
#include <vcl.h>
//---------------------------------------------------------------------------
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner){}
//---------------------------------------------------------------------------
HMODULE hRemoteModule=NULL;
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
bool bSuccess = false;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
if(!CreateProcess(NULL, "AppWithControl.exe", 0, 0, FALSE, 0, 0, 0, &si, &pi)) //Запускаем приложение с необходимыми контролами
{
ShowMessage(SysErrorMessage(GetLastError()));
} else
{
DWORD res = WaitForInputIdle(pi.hProcess, 10000); //Ставим таймер на 10 секунд
if(res == WAIT_TIMEOUT) //Если приложение не запустилось
{
if (MessageBoxA(Handle, "Превышен предел ожидания. Уничтожить процесс?", 0, MB_YESNO | 16) == IDYES)
{
TerminateProcess(pi.hProcess, 0);
}
} else
{
String DllPath = ExtractFilePath(Application->ExeName) + "ControlDLL.dll";
LPVOID p = VirtualAllocEx(pi.hProcess, 0, DllPath.Length() + 1, MEM_COMMIT, PAGE_READWRITE);
if (!p)
{
ShowMessage("Невозможно получить доступ к памяти процесса! Ошибка: " + SysErrorMessage(GetLastError()));
} else
{
if (!WriteProcessMemory(pi.hProcess, p, DllPath.c_str(), DllPath.Length() + 1, NULL))
{
ShowMessage("Невозможно получить доступ к памяти процесса!");
} else
{
FARPROC fp = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if(!fp)
{
ShowMessage("Невозможно получить адрес kernel32.dll!");
} else
{
HANDLE hThread = CreateRemoteThread(pi.hProcess, 0, 0, (LPTHREAD_START_ROUTINE)fp, (LPVOID)p, 0, NULL);
if(!hThread)
{
ShowMessage("Невозможно создать удаленный поток! Ошибка: " + SysErrorMessage(GetLastError()));
} else
{
res = WaitForSingleObject(hThread, 10000); //Ставим таймер на 10 секунд
if(res == WAIT_TIMEOUT) //Если время ожидания вышло
{
if (MessageBoxA(Handle, "Поток завис. Завершить его?", 0, 16 | MB_YESNO) == IDYES)
{
TerminateThread(hThread, 0);
}
}
GetExitCodeThread(hThread, (LPDWORD)&hRemoteModule);
if(hRemoteModule)
{
bSuccess = true;
} else
{
ShowMessage("Инициализация DLL в удалённом процессе завершена с ошибкой!");
}
CloseHandle(hThread);
}
}
}
VirtualFreeEx(pi.hProcess, p, DllPath.Length() + 1, MEM_FREE); //Освобождаем пямять
}
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
if(bSuccess) //Если все проверки прошли успешно
{
ShowMessage("Операция успешно завершена!");
}
}
//---------------------------------------------------------------------------
/****************************************************************************/
Думаю, проблем в создании динамического TTimer не возникнет.
Можно, конечно, обойтись и без таймера. Сделать можно приблизительно так:
Код:
/****************************************************************************/
//---------------------------------------------------------------------------
void __fastcall SetProgressHook(TCGauge* pThis, int progress);
//---------------------------------------------------------------------------
typedef void (__fastcall *SetProgressHookProto)(TCGauge*, int);
//---------------------------------------------------------------------------
SetProgressHookProto fp;
BYTE OldCode[6];
//---------------------------------------------------------------------------
#pragma option push
#pragma option -a1 // устанавливаем выравнивание на байт
struct {
BYTE push_op;
DWORD _addr;
BYTE ret_op;
} inj_code={0x68, (DWORD)SetProgressHook, 0xc3};
#pragma option pop
//---------------------------------------------------------------------------
void __fastcall InitHook() //Инициализация (установка хука)
{
//этот код должен выполниться только один раз!!!
Fp = (SetProgressHookProto)GetProcAddress(GetModuleHandle(0), "@TCGauge@SetProgress$qqrl");
if (fp)
{
DWORD dwOldProtect;
VirtualProtect(fp, sizeof(inj_code), PAGE_EXECUTE_READWRITE, &dwOldProtect); // разрешение на запись в сегмент кода
memcpy(OldCode, fp, sizeof(inj_code)); // сохранение старого кода
memcpy(fp, &inj_code, sizeof(inj_code)); // внедрение кода перехватчика
}
}
//---------------------------------------------------------------------------
void __fastcall SetProgressHook(TCGauge* pThis, int progress) //если прогресс изменится – сразу нам сообщит
{
memcpy(fp, OldCode, sizeof(inj_code));
fp(pThis, progress); // вызов оригинальной функции
memcpy(fp, &inj_code, sizeof(inj_code));
ShowMessage(progress); //показываем прогресс TCGauge
}
//---------------------------------------------------------------------------
void __fastcall SetProgressHook(TCGauge* pThis, int progress);
//---------------------------------------------------------------------------
typedef void (__fastcall *SetProgressHookProto)(TCGauge*, int);
//---------------------------------------------------------------------------
SetProgressHookProto fp;
BYTE OldCode[6];
//---------------------------------------------------------------------------
#pragma option push
#pragma option -a1 // устанавливаем выравнивание на байт
struct {
BYTE push_op;
DWORD _addr;
BYTE ret_op;
} inj_code={0x68, (DWORD)SetProgressHook, 0xc3};
#pragma option pop
//---------------------------------------------------------------------------
void __fastcall InitHook() //Инициализация (установка хука)
{
//этот код должен выполниться только один раз!!!
Fp = (SetProgressHookProto)GetProcAddress(GetModuleHandle(0), "@TCGauge@SetProgress$qqrl");
if (fp)
{
DWORD dwOldProtect;
VirtualProtect(fp, sizeof(inj_code), PAGE_EXECUTE_READWRITE, &dwOldProtect); // разрешение на запись в сегмент кода
memcpy(OldCode, fp, sizeof(inj_code)); // сохранение старого кода
memcpy(fp, &inj_code, sizeof(inj_code)); // внедрение кода перехватчика
}
}
//---------------------------------------------------------------------------
void __fastcall SetProgressHook(TCGauge* pThis, int progress) //если прогресс изменится – сразу нам сообщит
{
memcpy(fp, OldCode, sizeof(inj_code));
fp(pThis, progress); // вызов оригинальной функции
memcpy(fp, &inj_code, sizeof(inj_code));
ShowMessage(progress); //показываем прогресс TCGauge
}
//---------------------------------------------------------------------------
================================================
Автор ответа: frid-karatel
===============================================
37. Как реализовать поиск по HTML-странице?
Ответ ================================================
Код:
//in hpp
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "SHDocVw_OCX.h"
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TPanel *Panel1;
TButton *Button1;
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
TCppWebBrowser *CppWebBrowser;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//in cpp
...
#include "mshtmhst.h"
#include "mshtmcid.h"
#include "mshtml.h"
...
#define HTMLID_FIND 1
...
const GUID CGID_IWebBrowser =
{0xed016940, 0xbd5b, 0x11cf,
{0xba, 0x4e, 0x0, 0xc0, 0x4f, 0xd7, 0x08, 0x16}} ;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
LPDISPATCH lpDispatch = CppWebBrowser->ControlInterface->get_Document();
if(lpDispatch)
{
IOleCommandTarget* pcmd=NULL;
if( SUCCEEDED(lpDispatch->QueryInterface(IID_IOleCommandTarget,(void**)&pcmd) ) )
{
pcmd->Exec(&CGID_IWebBrowser, HTMLID_FIND, 0, NULL, NULL);
pcmd->Release();
}
lpDispatch->Release();
}
}
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "SHDocVw_OCX.h"
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TPanel *Panel1;
TButton *Button1;
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
TCppWebBrowser *CppWebBrowser;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//in cpp
...
#include "mshtmhst.h"
#include "mshtmcid.h"
#include "mshtml.h"
...
#define HTMLID_FIND 1
...
const GUID CGID_IWebBrowser =
{0xed016940, 0xbd5b, 0x11cf,
{0xba, 0x4e, 0x0, 0xc0, 0x4f, 0xd7, 0x08, 0x16}} ;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
LPDISPATCH lpDispatch = CppWebBrowser->ControlInterface->get_Document();
if(lpDispatch)
{
IOleCommandTarget* pcmd=NULL;
if( SUCCEEDED(lpDispatch->QueryInterface(IID_IOleCommandTarget,(void**)&pcmd) ) )
{
pcmd->Exec(&CGID_IWebBrowser, HTMLID_FIND, 0, NULL, NULL);
pcmd->Release();
}
lpDispatch->Release();
}
}
//---------------------------------------------------------------------------
================================================
Автор ответа: ***
===============================================