Display help topic from CHM on a VCL TPanel? - c++builder

Using C++ Builder 10 Seattle (CX10).
I have a .chm with map IDs for certain topics. I can load the topics into an external window like this:
#include "Vcl.HTMLHelpViewer.hpp"
#pragma link "Vcl.HTMLHelpViewer"
// In the main form constructor:
Application->HelpFile = ExtractFilePath(Application->ExeName) + "MyHelp.chm";
// In button click event handler:
Application->HelpContext(10001);
This is great for many situations, but sometimes I want to embed the context-specific help within my TForm, such as on a TPanel. I found pieces of information about using WinAPI functions FindWindow and SetParent. So I tried this:
HWND t_hwnd = FindWindow(NULL, "My Help File");
if (t_hwnd)
{
// HelpPanel is a TPanel with no properties adjusted from default
::SetParent(t_hwnd, HelpPanel->Handle);
}
Which compiles, links, runs and doesn't crash... but the subsequent call to Application->HelpContext(10001) still displays the topic in the external window, and not in the HelpPanel.
I am guessing that the easy-to-use Application->HelpContext call isn't what I need for redirecting to a VCL control, but I don't know where to look next.
Following up on the comments, here is where I am: I found out the ilink32 error (see my comment, below) was because I need to load HHCTRL.ocx in order to make a call to HtmlHelpA. So here is my test project code, a form with a TRadioGroup and TPanel. Only one radio button attempts to place the topic on the TPanel; the rest use Application->HelpContext. All of this compiles, links and runs, but the call to place the help on TPanel doesn't do anything visible.
Really hoping somebody can help... thanks.
// MainFrm.dfm
object MainForm: TMainForm
Left = 0
Top = 0
Caption = 'MainForm'
ClientHeight = 486
ClientWidth = 686
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object FunctionsRadioGroup: TRadioGroup
Left = 8
Top = 8
Width = 185
Height = 105
Caption = 'EDITS Language Functions'
Items.Strings = (
'LOOKUP'
'RLOOKUP'
'ILOOKUP'
'STRCPY')
TabOrder = 0
OnClick = FunctionsRadioGroupClick
end
object HelpPanel: TPanel
Left = 199
Top = 8
Width = 490
Height = 477
Caption = 'HelpPanel'
TabOrder = 1
end
end
// MainFrm.h
#ifndef MainFrmH
#define MainFrmH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
typedef HWND (WINAPI *FPHH) (HWND, LPCSTR, UINT, DWORD);
// Map IDs in my CHM
#define LANG_FUNC_LOOKUP 10001
#define LANG_FUNC_RLOOKUP 10002
#define LANG_FUNC_STRCPY 10004
#define LANG_FUNC_ILOOKUP 10003
class TMainForm : public TForm
{
__published: // IDE-managed Components
TRadioGroup *FunctionsRadioGroup;
TPanel *HelpPanel;
void __fastcall FunctionsRadioGroupClick(TObject *Sender);
private: // User declarations
HINSTANCE FHHCTRL_OCX_INST;
FPHH htmlHelp;
bool __fastcall load_HHCTRL_OCX();
public: // User declarations
__fastcall TMainForm(TComponent* Owner);
__fastcall ~TMainForm();
void __fastcall DoShowEmbeddedHelp(TPanel* ThePanel, NativeInt TheTopicID);
};
//---------------------------------------------------------------------------
extern PACKAGE TMainForm *MainForm;
//---------------------------------------------------------------------------
#endif
// MainFrm.cpp
#include <vcl.h>
#pragma hdrstop
#include "MainFrm.h"
#include <Vcl.HTMLHelpViewer.hpp>
#include <HtmlHelp.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "Vcl.HTMLHelpViewer"
//#pragma link "htmlhelp.lib"
#pragma resource "*.dfm"
TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
Application->HelpFile = ExtractFilePath(Application->ExeName) +
"MyHelpFile.chm";
FHHCTRL_OCX_INST = 0;
} // ctor
//---------------------------------------------------------------------------
__fastcall TMainForm::~TMainForm()
{
if (FHHCTRL_OCX_INST > 0)
{
FreeLibrary(FHHCTRL_OCX_INST);
}
}// dtor
//---------------------------------------------------------------------------
void __fastcall TMainForm::FunctionsRadioGroupClick(TObject *Sender)
{
TRadioGroup* t_radio = dynamic_cast<TRadioGroup*>(Sender);
if (t_radio)
{
switch (t_radio->ItemIndex)
{
case 0:
//Application->HelpContext(LANG_FUNC_LOOKUP);
DoShowEmbeddedHelp(HelpPanel, LANG_FUNC_LOOKUP);
break;
case 1:
Application->HelpContext(LANG_FUNC_RLOOKUP);
break;
case 2:
Application->HelpContext(LANG_FUNC_ILOOKUP);
break;
case 3:
Application->HelpContext(LANG_FUNC_STRCPY);
break;
}
}
}
//---------------------------------------------------------------------------
bool __fastcall TMainForm::load_HHCTRL_OCX()
{
bool t_is_loaded = (FHHCTRL_OCX_INST > 0);
if (!t_is_loaded)
{
FHHCTRL_OCX_INST = LoadLibrary("HHCTRL.OCX");
if (FHHCTRL_OCX_INST > 0)
{
(FARPROC&) htmlHelp = GetProcAddress(FHHCTRL_OCX_INST, "HtmlHelpA");
if (htmlHelp)
{
t_is_loaded = true;
}
}
}
return t_is_loaded;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::DoShowEmbeddedHelp(TPanel* ThePanel, NativeInt TheTopicID)
{
HH_WINTYPE wintypedef;
AnsiString t_helpfile = ExtractFilePath(Application->ExeName) + "MyHelpFile.chm";
AnsiString TheWinName = "HelpPanel";
if (!FileExists(t_helpfile))
{
MessageDlg(AnsiString("Help file not found: ") + t_helpfile,
mtError, TMsgDlgButtons() << mbOK, 0);
return;
}
// Zero the structure
memset(&wintypedef, 0, sizeof(HH_WINTYPE));
// Prepare the properties
wintypedef.cbStruct = sizeof(wintypedef);
wintypedef.fUniCodeStrings = false;
wintypedef.pszType = TheWinName.c_str();
wintypedef.fsValidMembers =
HHWIN_PARAM_PROPERTIES |
HHWIN_PARAM_STYLES |
HHWIN_PARAM_EXSTYLES |
HHWIN_PARAM_RECT |
HHWIN_PARAM_NAV_WIDTH |
HHWIN_PARAM_SHOWSTATE |
HHWIN_PARAM_TB_FLAGS |
HHWIN_PARAM_EXPANSION;
wintypedef.fsWinProperties =
HHWIN_PROP_NOTITLEBAR |
HHWIN_PROP_NO_TOOLBAR |
HHWIN_PROP_NODEF_STYLES |
HHWIN_PROP_NODEF_EXSTYLES |
HHWIN_PROP_TRI_PANE;
wintypedef.pszCaption = "";
wintypedef.dwStyles = WS_VISIBLE | WS_CHILDWINDOW;
wintypedef.dwExStyles = WS_EX_LEFT;
wintypedef.rcWindowPos =
Rect(0, 0, ThePanel->ClientWidth, ThePanel->ClientHeight);
wintypedef.nShowState = SW_SHOW;
wintypedef.fsToolBarFlags = HHWIN_BUTTON_PRINT | HHWIN_BUTTON_BACK ;
wintypedef.fNotExpanded = true;
if (load_HHCTRL_OCX())
{
if ((int)htmlHelp(0, NULL, HH_SET_WIN_TYPE, (DWORD)&wintypedef) < 0)
{
ShowMessage("Help failed on topic");
}
else
{
/* NOTE: This was close, but wrong.
int HelpWinHandle =
(int)htmlHelp(ThePanel->Handle, "HelpPanel", HH_HELP_CONTEXT, TheTopicID);
*/
AnsiString t_fn = t_helpfile + AnsiString(">HelpPanel");
int HelpWinHandle =
(int)htmlHelp(ThePanel->Handle, t_fn.c_str(), HH_HELP_CONTEXT, TheTopicID);
}
}
} // DoShowEmbeddedHelp
//---------------------------------------------------------------------------

This is deep going into HTMLHelp API (written in C++ 20 years ago by Ralph Walden). You maybe warned ...
I have experience in help authoring and I'm not a C++ programmer. So, the HTMLHelp Viewer hh.exe is a wrapper for Internet Explorer API showing the CHM's HTML topics in the content pane on the right.
You know "Application->HelpContext(10001);" is calling the Help Viewer with the specified topicId "10001" always. Embedded help is less in use and today not what the users want. A second help window is easier of course.
Some ideas and a trick e.g. to shrink the viewer done by the help author (creator of the CHM file) you'll see at:
Microsoft HTML Help - Get the topic page URL from the topic ID
Further information - sorry Delphi - you'll find at:
How to control/remove borders of embedded chm help file in delphi windows/vcl application?
HTH

All right, I finally figured it out.
In the code I posted for function TMainForm::DoShowEmbeddedHelp, I did not properly prepare the second parameter to HtmlHelpA. It SHOULD be this:
AnsiString t_fn = t_helpfile + AnsiString(">HelpPanel");
HelpWinHandle =
(int)htmlHelp(ThePanel->Handle, t_fn.c_str(), HH_HELP_CONTEXT, TheTopicID);
Now I am getting the result I wanted.

Related

Indy TCP client-server don't work with OpenSSL

In C++ Builder 10.3.1 I am using Indy TCP client-server components (TIdTCPClient & TIdTCPServer) to create an example of encrypted communication with OpenSSL. I'm using this sample code:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
C1->Connect();
C1->Socket->Write(4);
int res = C1->Socket->ReadInt32();
C1->Disconnect();
ShowMessage(res);
}
void __fastcall TForm1::S1Execute(TIdContext *AContext)
{
int x = AContext->Connection->Socket->ReadInt32();
AContext->Connection->Socket->Write(x * x);
AContext->Connection->Disconnect();
}
Without OpenSSL everything works fine, but after adding IdSSLIOHandlerSocketOpenSSL1 and IdServerIOHandlerSSLOpenSSL1 components and assigning them to TCP client-server components (IOHandler property) I get the error "Could not load SSL library". In that case I used OpenSSL 1.0.2 binaries (ssleay32.dll and libeay32.dll) from https://indy.fulgan.com/SSL/.
But, I managed to find older OpenSSL libraries that were successfully loaded. Still, then I get the following error:
Error connecting with SSL. EOF was observed that violates the protocol.
How to make this work?
EDIT: After setting PassThrough to false both on client & server side I get:
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
EDIT: Here is my Form's full code and DFM:
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::Button1Click(TObject *Sender)
{
IdSSLIOHandlerSocketOpenSSL1->PassThrough = false;
C1->Connect();
C1->Socket->Write(5);
int res = C1->Socket->ReadInt32();
C1->Disconnect();
ShowMessage(res);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::S1Execute(TIdContext *AContext)
{
int x = AContext->Connection->Socket->ReadInt32();
AContext->Connection->Socket->Write(x * x);
AContext->Connection->Disconnect();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::S1Connect(TIdContext *AContext)
{
static_cast<TIdSSLIOHandlerSocketOpenSSL*>(AContext->Connection->Socket)->PassThrough = false;
}
//---------------------------------------------------------------------------
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdCustomTCPServer.hpp>
#include <IdIOHandler.hpp>
#include <IdIOHandlerSocket.hpp>
#include <IdIOHandlerStack.hpp>
#include <IdServerIOHandler.hpp>
#include <IdSSL.hpp>
#include <IdSSLOpenSSL.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
#include <IdTCPServer.hpp>
#include <IdContext.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TIdTCPClient *C1;
TIdTCPServer *S1;
TIdServerIOHandlerSSLOpenSSL *IdServerIOHandlerSSLOpenSSL1;
TIdSSLIOHandlerSocketOpenSSL *IdSSLIOHandlerSocketOpenSSL1;
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall S1Execute(TIdContext *AContext);
void __fastcall S1Connect(TIdContext *AContext);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.dfm
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 299
ClientWidth = 635
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 24
Top = 208
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object C1: TIdTCPClient
IOHandler = IdSSLIOHandlerSocketOpenSSL1
ConnectTimeout = 0
Host = '127.0.0.1'
IPVersion = Id_IPv4
Port = 5577
ReadTimeout = -1
Left = 168
Top = 96
end
object S1: TIdTCPServer
Active = True
Bindings = <
item
IP = '0.0.0.0'
Port = 5577
end>
DefaultPort = 0
IOHandler = IdServerIOHandlerSSLOpenSSL1
OnConnect = S1Connect
OnExecute = S1Execute
Left = 240
Top = 96
end
object IdServerIOHandlerSSLOpenSSL1: TIdServerIOHandlerSSLOpenSSL
SSLOptions.Mode = sslmUnassigned
SSLOptions.VerifyMode = []
SSLOptions.VerifyDepth = 0
Left = 464
Top = 40
end
object IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL
Destination = '127.0.0.1:5577'
Host = '127.0.0.1'
MaxLineAction = maException
Port = 5577
DefaultPort = 0
SSLOptions.Mode = sslmUnassigned
SSLOptions.VerifyMode = []
SSLOptions.VerifyDepth = 0
Left = 320
Top = 184
end
end
after adding IdSSLIOHandlerSocketOpenSSL1 and IdServerIOHandlerSSLOpenSSL1 components and assigning them to TCP client-server components (IOHandler property) I get the error "Could not load SSL library".
Make sure that you have up-to-date OpenSSL 1.0.2 DLLs (Indy does not yet support OpenSSL 1.1.x) in your app's folder, or in a folder that you specify with the IdOpenSSLSetLibPath() function in IdSSLOpenSSLHeaders.hpp at program startup.
If you are still having the error, you can use Indy's WhichFailedToLoad() function in IdSSLOpenSSLHeaders.hpp to find out why the DLLs are not loading - either because the DLLs themselves cannot be found or loaded into memory, or because they are missing required exported functions that Indy uses.
In that case I used OpenSSL 1.0.2 binaries (ssleay32.dll and libeay32.dll) from https://indy.fulgan.com/SSL/.
Those DLLs are known to work fine with Indy.
then I get the following error:
Error connecting with SSL. EOF was observed that violates the protocol.
That error means the server closed the TCP connection on its end while the client was still performing the SSL/TLS handshake. That can happen, for instance, if an exception is raised on the server side. By default, TIdTCPServer handles an uncaught exception by closing the socket.
It is a common mistake not to set the TIdSSLIOHandlerSocketOpenSSL::PassThrough property to false on the server side. It needs to be set manually, as TIdTCPServer does not set it automatically, to allow users to decide which port(s) should use SSL/TLS. PassThrough needs to be set to true on both ends of the connecton.
On the client side, you can set PassThrough before calling Connect() (ie, for implicit SSL) or after (ie, for STARTTLS-like commands).
On the server side, you can set PassThrough in the OnConnect event (ie, for implicit SSL) or in the OnExecute event (ie, for STARTTLS-like commands).
In your example, try this:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdSSLIOHandlerSocketOpenSSL1->PassThrough = false;
C1->Connect();
C1->Socket->Write(4);
int res = C1->Socket->ReadInt32();
C1->Disconnect();
ShowMessage(res);
}
void __fastcall TForm1::S1Connect(TIdContext *AContext)
{
static_cast<TIdSSLIOHandlerSocketOpenSSL*>(AContext->Connection->Socket)->PassThrough = false;
}
void __fastcall TForm1::S1Execute(TIdContext *AContext)
{
int x = AContext->Connection->Socket->ReadInt32();
AContext->Connection->Socket->Write(x * x);
AContext->Connection->Disconnect();
}
And, needless to say, make sure the IOHandlers on both sides are configured similarly to use compatible SSL/TLS protocol versions, certificates, etc.
Make sure you use the 32 bits OpenSSL DLLs (i386-win32) if your program is 32 bits.

How RichEdit can accept file drag & dropping in BCB or Delphi program?

I'm writing a program that could drag and drop text files onto the form to show and edit it by RichEdit.
I've used ChangeWindowMessageFilterEx to make sure that WM_DROPFILES and WM_COPYDATA can received by my Main Form:
ChangeWindowMessageFilterEx(Handle, WM_DROPFILES, MSGFLT_ADD, NULL);
ChangeWindowMessageFilterEx(Handle, WM_COPYDATA, MSGFLT_ADD, NULL);
ChangeWindowMessageFilter(73 , MSGFLT_ADD);
and call DragAcceptFiles(Handle, true) in the form creation function.
Now the drag operation is valid on any places of the window but except the RichEdit, the cursor shows a deny icon when dragging on the RichEdit.
Dragging on any components, eg. text editors, panels, combo boxes and buttons, on the form can lead to receive the WM_DROPFILES message, but except RichEdit.
Actually, I'm sure that it is possible to drag files on the RichEdit because I have wrote the code last year, but I have lost the source code and forgot it. I'm trying to rebuild the same one now.
Here is the google drive download link to the executable file that I have finished last year. And here is the github url to the uncompleted source code that I'm writing currently.
Thank you for your watching.
I don't know why TRichEdit does not receive WM_DROPFILES when using a message map, but you could handle the WindowProc of the TRichEdit.
A possilble implementation could look like this:
Drop a TRichEdit on your Form
Modify header file
private:
TWndMethod OldWindowProc;
void __fastcall NewWindowProc(TMessage& Msg);
Add implementation
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
OldWindowProc = RichEdit1->WindowProc;
RichEdit1->WindowProc = NewWindowProc;
DragAcceptFiles(RichEdit1->Handle, true);
}
void __fastcall TForm1::NewWindowProc(TMessage& Msg)
{
switch (Msg.Msg) {
case WM_DROPFILES:
{
HDROP DropH = (HDROP)Msg.WParam;
int droppedFileCount = DragQueryFile(DropH, 0xFFFFFFFF, NULL, 0);
TStringList* Buffer = new TStringList();
for (int i = 0; i < droppedFileCount; i++) {
int fileNameLength = DragQueryFile(DropH, i, NULL, 0);
String FileName;
FileName.SetLength(fileNameLength);
DragQueryFile(DropH, i, FileName.w_str(), fileNameLength + 1);
Buffer->LoadFromFile(FileName);
RichEdit1->Lines->AddStrings(Buffer);
RichEdit1->Lines->Add("");
}
delete Buffer;
DragFinish(DropH);
Msg.Result = 0;
break;
}
case CM_RECREATEWND:
DragAcceptFiles(RichEdit1->Handle, true);
break;
default:;
}
OldWindowProc(Msg);
}

DirectX 12 device suspended immediately after creation

I am getting a strange error when creating the DirectX 12 command queue.
Other DX12 applications are able to launch successfully on the same machine.
My computer uses the D3D_FEATURE_LEVEL_11_0 if block.
The graphics card used for testing is NVIDIA GT 740, with 361.75 drivers
This is the code in use (minimized):
#include <Windows.h>
#include <d3d12.h>
#include <dxgi1_4.h>
#include <comdef.h>
#include <D3d12sdklayers.h>
#include <string>
#pragma comment(lib,"d3d12.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"d3dcompiler.lib")
using namespace std;
LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(nCmdShow);
UNREFERENCED_PARAMETER(lpCmdLine);
wchar_t* WindowClass = L"Papergate";
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
wc.lpszClassName = WindowClass;
if (!RegisterClassEx(&wc))
{
return 1;
}
HWND hwnd = CreateWindowEx(NULL, wc.lpszClassName, WindowClass,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
if (!hwnd)
{
UnregisterClass(WindowClass, hInstance);
return 1;
}
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
ID3D12Device* device;
HRESULT result = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_12_1,
__uuidof(ID3D12Device), (void**)&device);
if (FAILED(result))
{
result = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_12_0,
__uuidof(ID3D12Device), (void**)&device);
if (FAILED(result))
{
result = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0,
__uuidof(ID3D12Device), (void**)&device);
if (FAILED(result)) {
_com_error error(result);
MessageBox(hwnd, error.ErrorMessage(),
(wstring(L"Error: ") + to_wstring(__LINE__)).c_str(),
MB_OK);
return 2;
}
}
}
ID3D12Debug* debugInterface;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface))))
{
debugInterface->EnableDebugLayer();
}
D3D12_COMMAND_QUEUE_DESC commandQueueDesc;
commandQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
commandQueueDesc.NodeMask = 0;
commandQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
commandQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
ID3D12CommandQueue* commandQueue;
result = device->CreateCommandQueue(&commandQueueDesc, __uuidof(ID3D12CommandQueue), (void**)&commandQueue);
if (FAILED(result)) {
_com_error error(result);
MessageBox(hwnd, error.ErrorMessage(),
(wstring(L"Error: ") + to_wstring(__LINE__)).c_str(), MB_OK);
result = device->GetDeviceRemovedReason();
error = _com_error(result);
MessageBox(hwnd, error.ErrorMessage(),
(wstring(L"Error: ") + to_wstring(__LINE__)).c_str(), MB_OK);
debugInterface->Release(); device->Release(); return 2;
}
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
while (GetMessage(&msg, NULL, 0, 0) && msg.message != WM_QUIT)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
commandQueue->Release();
device->Release();
UnregisterClass(WindowClass, hInstance);
return 0;
}
I am getting the following errors on lines 97 and 102, respectively:
The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action.
Second error:
The GPU will not respond to more commands, most likely because some other application submitted invalid commands.
The calling application should re-create the device and continue.
This seems quite likely to be a driver bug of some kind. Check to see if there are updated drivers for your hardware. You should try using the Direct3D12 Game templates in this VSIX and see if they hit the same kind of issue (for more details on the templates see this blog post).
Your cascade pattern of calling D3D12CreateDevice for various feature levels is unusual and is not necessary. If your application can run on Direct3D Feature Level 11.0 or greater, then just use D3D_FEATURE_LEVEL_11_0 once. You should pass whatever your minimum supported feature level is to this function.
If the Direct3D 12 device does support a higher feature level, you can discover that by using CheckFeatureSupport either by checking for the individual features or by using D3D12_FEATURE_FEATURE_LEVELS:
// Create the DX12 API device object.
DX::ThrowIfFailed(D3D12CreateDevice(
adapter.Get(),
m_d3dMinFeatureLevel,
IID_PPV_ARGS(&m_d3dDevice)
));
// Determine maximum supported feature level for this device
static const D3D_FEATURE_LEVEL s_featureLevels[] =
{
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
};
D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels =
{
_countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0
};
HRESULT hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS,
&featLevels, sizeof(featLevels));
if (SUCCEEDED(hr))
{
m_d3dFeatureLevel = featLevels.MaxSupportedFeatureLevel;
}
else
{
m_d3dFeatureLevel = m_d3dMinFeatureLevel;
}
Keep in mind that D3D_FEATURE_LEVEL_12_0 and D3D_FEATURE_LEVEL_12_1 are essentially just D3D_FEATURE_LEVEL_11_1 with a few optional features made mandatory. If your app is already checking for them at 11.x then there's no reason to 'require' 12.0 or 12.1. See MSDN.
For the vast majority of Direct3D 12 games & applications, D3D_FEATURE_LEVEL_11_0 or D3D_FEATURE_LEVEL_11_1 are good choices. Keep in mind that while AMD/ATI supported Feature Level 11.1 pretty early, NVIDIA DirectX 11 parts only supported 11.0 with some optional features for some time.

XE4 Delphi TCustomListView TViewStyle 'vsSmallIcon' badly arranged Icons

I'm using TListView in my form (which inherits from TCustomListView) and when I change ListView style to "vsSmallIcon" the icons gets badly arranged. We found this issue ever since we ported our Code from Borland 2006 to XE4. Rest all "ViewStyle"s like vsIcon, vsList & vsReport are working fine. Did anyone faced similar issue with VCL's TlistView component?
I have already tried ListView1->Arrange(arDefault) and 'AutoArrange' Icon Options but nothing seems to work for 'vsSmallIcon' TViewStyle.
I'm on Windows 7 and using RAD Studio XE4 with Update1.
Thanks,
Santosh Thankachan
PS: Added an image to show this issue with vsSmallIcon TViewStyle.
Code is as follows:
//SmallIconIssue.h
#ifndef SmallIconsIssueH
#define SmallIconsIssueH
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ImgList.hpp>
#include <Vcl.ComCtrls.hpp>
class TSmallIconTest : public TForm
{
__published: // IDE-managed Components
TImageList *ImageList1;
TComboBox *ComboBox1;
TListView *ListView1;
TLabel *Label1;
void __fastcall FormCreate(TObject *Sender);
void __fastcall ComboBox1Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TSmallIconTest(TComponent* Owner);
};
extern PACKAGE TSmallIconTest *SmallIconTest;
#endif
//SmallIconIssue.cpp
#pragma package(smart_init)
#pragma resource "*.dfm"
TSmallIconTest *SmallIconTest;
__fastcall TSmallIconTest::TSmallIconTest(TComponent* Owner) : TForm(Owner) {}
void __fastcall TSmallIconTest::FormCreate(TObject *Sender) {
const char Names[42][2][10] =
{{"Rubble","Barny"},
{"Michael", "Johnson"},
{"Bunny", "Bugs"},
{"Silver", "HiHo"},
{"Silver1", "HiHo1"},
{"Silver2", "HiHo2"},
{"Silver3", "HiHo3"},
{"Silver4", "HiHo4"},
{"Silver5", "HiHo5"},
{"Silver6", "HiHo6"},
{"Silver7", "HiHo7"},
{"Silver8", "HiHo8"},
{"Silver9", "HiHo9"},
{"Silver11", "HiHo11"},
{"Silver22", "HiHo22"},
{"Silver33", "HiHo33"},
{"Silver44", "HiHo44"},
{"Silver55", "HiHo55"},
{"Silver66", "HiHo66"},
{"Silver77", "HiHo77"},
{"Simpson1", "Bart1"},
{"Simpson2", "Bart2"},
{"Simpson3", "Bart3"},
{"Simpson4", "Bart4"},
{"Simpson5", "Bart5"},
{"Simpson6", "Bart6"},
{"Simpson7", "Bart7"},
{"Simpson8", "Bart8"},
{"Simpson9", "Bart9"},
{"Simpson11", "Bart11"},
{"Simpson22", "Bart22"},
{"Simpson33", "Bart33"},
{"Simpson44", "Bart44"},
{"Simpson55", "Bart55"},
{"Simpson66", "Bart66"},
{"Simpson77", "Bart77"},
{"Simpson88", "Bart88"},
{"Simpson99", "Bart99"},
{"Simpson00", "Bart00"},
{"Simpson12", "Bart12"},
{"Simpson13", "Bart13"},
{"Squirrel", "Rocky"}};
TListItem *Item;
TListColumn *Column;
const char imagenames[30][30] = {
"Borland2 Image akjlhfkja",
"Borland3 Imagewerq r",
"Borland4 Rest qew reqwr",
"Borland5 Imagedf fa",
"Borland6 Free df ",
"Borland7 Image af ",
"Borland8 Clear ad3e",
"Borland9 Image123 ",
"Borland11 df d",
"Borland22 Imagea fa f",
"Borland33 hmmm f sdf f",
"C++ Image",
"Borland1 Test",
"Borland44 Imageq3r r",
"Borland55 abcdefg rest",
"Borland66 Imageq tr trt",
"Borland77 no rest atall dg",
"Borland88 Imageqtree",
"Borland99 Free VCL tree",
"Borland12 Imagedf fa",
"Borland23 Blurr df d",
"Borland34 r",
"Borland45 Rest qew reqwr",
"Borland56 Free df ",
"Borland67 Image123 ",
"Borland78 Imagea fa f",
"Borland89 Being",
"Borland90 AdFree",
"Borland13 Image akjlhfkja",
"Delphi23 Image color"
};
const char Col2Array[30][60] =
{
"Documentation for the C++ icon.",
"Borland1 icon test.",
"Borland2 icon. Rest sar",
"Borland3 icon Free .",
"Borland4 icon Tree. af",
"Borland6 icon Kree kjadsf k.",
"Borland7 icon lest hghghg.",
"Borland8 icon mnmnm.",
"Borland9 icon jiop werq .",
"Borland0 icon terere df af .",
"Borland5 icon nmijh fdferfr .",
"Borland11 icon Clear vc.",
"Borland22 icon Image sdgfsdg.",
"Borland33 icon Picture t4.",
"Borland44 iconv Congress25245.",
"Borland55 icon Labor 25v545.",
"Borland66 icon tony b3764656.",
"Borland77 icon 5 Abott reg354.",
"Borland88 icon. Rest sar",
"Borland99 icon Kevin 342455vreg354.",
"Borland00 icon test.",
"Borland12 icon Free .",
"Borland23 icon Kree kjadsf k.",
"Borland34 con Tree. af",
"Borland56 icon nmijh fdferfr .",
"Borland45 icon mnmnm.",
"Borland56 icon jiop werq .",
"Borland78 icon terere df af .",
"Borland89 icon lest hghghg.",
"Delphi90 icon Rudd 45c rewffretew."
};
ListView1->SmallImages = ImageList1;
ListView1->LargeImages = ImageList1;
for (int i = 0; i < ImageList1->Count; i++)
{
Item = ListView1->Items->Add();
Item->Caption = imagenames[i];
Item->ImageIndex = i;
Item->SubItems->Add(Col2Array[i]);
}
// Create two columns to show during viewing as vsReport
Column = ListView1->Columns->Add();
Column->Caption = "Image Name";
Column->Width = 200;
Column = ListView1->Columns->Add();
Column->Caption = "Image Description";
Column->Width = 200;
// Add View styles and constants to the Combo Box
ComboBox1->Items->AddObject("vsIcon", reinterpret_cast<TObject *>(vsIcon));
ComboBox1->Items->AddObject("vsList", reinterpret_cast<TObject *>(vsList));
ComboBox1->Items->AddObject("vsReport", reinterpret_cast<TObject *>(vsReport));
ComboBox1->Items->AddObject("vsSmallIcon", reinterpret_cast<TObject *>(vsSmallIcon));
// Display First item in the Combo Box and arrange ListView accordingly...
ComboBox1->ItemIndex = 0;
ListView1->ViewStyle = (TViewStyle) ComboBox1->Items->Objects[ComboBox1->ItemIndex];
ListView1->Arrange(arDefault);
}
void __fastcall TSmallIconTest::ComboBox1Click(TObject *Sender)
{
ListView1->ViewStyle = (TViewStyle) ComboBox1->Items->Objects[ComboBox1->ItemIndex];
ListView1->Arrange(arDefault);
}

TYPE_E_LIBNOTREGISTERED(Library not registered) while call Invoke() of unregistered ActiveX control?

Code as below. How to avoid the TYPE_E_LIBNOTREGISTERED(hr=0x8002801D, Library not registered) error(DO NOT register the ActiveX to Windows) of disp->Invoke()?
When register the ActiveX control, all is OK, but I want not register to WINDOWS.
Thanks!
#define WIN32_LEAN_AND_MEAN
#include <tchar.h>
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
#include <ole2.h>
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
OleInitialize(NULL);
LPCTSTR lpFile = _T("D:\\Temp\\Flash32_11_4_402_287.ocx");
HMODULE hDll = LoadLibrary(lpFile);
if (hDll)
{
typedef HRESULT (WINAPI *DllGetClassObject_t)(REFCLSID, REFIID, LPVOID*);
DllGetClassObject_t DllGetClassObject = NULL;
DllGetClassObject = (DllGetClassObject_t)GetProcAddress(hDll, "DllGetClassObject");
if (DllGetClassObject)
{
CLSID clsid = GUID_NULL;
IClassFactory *pCF = NULL;
if (SUCCEEDED(CLSIDFromString(L"{D27CDB6E-AE6D-11CF-96B8-444553540000}", &clsid))
&& SUCCEEDED(DllGetClassObject(clsid, IID_IClassFactory, (void**)&pCF)))
{
IOleObject *obj = NULL;
IDispatch *disp = NULL;
if (SUCCEEDED(pCF->CreateInstance(NULL, IID_IOleObject, (void**)&obj))
&& SUCCEEDED(obj->QueryInterface(IID_IDispatch, (void**)&disp)))
{
DISPPARAMS params = { NULL, NULL, 0, 0 };
HRESULT hr = disp->Invoke(0x70, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&params, NULL, NULL, NULL);
assert(SUCCEEDED(hr));
//ERROR: hr=0x8002801D,TYPE_E_LIBNOTREGISTERED, Library not registered
}
if (disp) disp->Release();
if (obj) obj->Release();
pCF->Release();
}
}
}
OleUninitialize();
return 0;
}
To Hans Passant:
Thanks very very much. English is not my mother tongue, but under you detailed answers, I have the perfect solution to this problem, and this is my first question on stackoverflow, thanks again. As you said, my solution is bellow:
//ITypeInfo *m_ti = NULL;
//pCF->CreateInstance(...);
ITypeLib *tl = NULL;
if (SUCCEEDED(LoadTypeLib(wsOcxFile, &tl)))
{
if (SUCCEEDED(tl->GetTypeInfoOfGuid(guid, &m_ti)))
{
hr = m_ti->Invoke(disp,
dispid, wFlags, &m_dispParams,
pvResult, &ei, &nArgErr);
}
tl->Release();
}
//m_ti->Release();

Resources