using DirectShow in Winforms - winforms

i could run the How To Play a File code sample in c++ win32 console application, but when i try to implement it by winforms i get these Link errors:
Error 2 error LNK2020: unresolved token (0A000016) IID_IMediaEvent
Error 3 error LNK2020: unresolved token (0A000017) IID_IMediaControl
and some more link errors .....
here is the code of the form:
#include <dshow.h>
#pragma comment(lib, "Strmiids.lib")
namespace Form1 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->SuspendLayout();
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(284, 262);
this->Name = L"Form1";
this->Text = L"Form1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change this string to a file on your system.
hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}
};
}
How can i setup the build environment in winforms to do the DirectShow programming?
im using windows SDK v7.1 And vc++ 2010

You are not getting a great diagnostic. The problem is that DirectShow is native code. But you are letting the compiler think it is okay to compile it in managed mode. Which works surprisingly well, until the linker takes a nosedive. You need to make it look like this:
#pragma once
#pragma managed(push, off)
#include <dshow.h>
#pragma managed(pop)
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "ole32.lib")
// etc..
This probably generates a flurry of errors. Right-click the project in the Solution Explorer window, Properties, Configuration Properties, General. Change Common Language Runtime support from /clr:pure to /clr. This played a sample .avi file properly when I tried it. In a DirectShow window, not the form. The sample code was designed only to work in a console application. You should also remove the calls to CoInitialize and CoUninitialize, .NET already initializes COM. Improving the error handling is advisable. Consider embedding Windows Media Player instead.

Related

Fatal error c1001 when trying to make a GUI program in C++ CLR using .NET core in MSVS Enterprise 2019 16.4.6

I tried to make a C++ GUI program, i started with an empty project, and then add source file which is UI->windows form, and made a main function to call it. But when i tried to run it, it always shows this error
C1001 An internal error has occurred in the compiler
I also set the linker->system->subsystem into windows(/subsystem:windows)
and set entry point to my main function.
this is my main cpp file.
#include "MyForm.h"
using namespace Project1;
using namespace System::Windows::Forms;
using namespace System::Windows;
int main()
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Project1::MyForm form;
Application::Run(% form);
}
this is my header file(automaticaly created by VS)
#pragma once
namespace Project1 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for MyForm
/// </summary>
public ref class MyForm : public System::Windows::Forms::Form
{
public:
MyForm(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~MyForm()
{
if (components)
{
delete components;
}
}
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->SuspendLayout();
//
// MyForm
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(1089, 508);
this->Name = L"MyForm";
this->Text = L"MyForm";
this->ResumeLayout(false);
}
#pragma endregion
};
}
it has over 2k warning, i can't possibly put it all here

C++ form unresponsive on start

i'm working on my first C++ project that requires a form and I've seemed to have gone in way over my head. largely I believe my issue has to do with that I'm not multi threading my form, but I'm unsure of the proper implementation. I was hoping someone could point out to me exactly where I've gone and made myself look like a muppet. (warning for the feint of heart, I used global variables to quickly create a proof of concept, once I have everything working more or less correctly I'll go back and properly protect everything)
*edit: I guess to clarify, it looks like the issue is that i execute everything in the main thread, its is possible to create a single new thread for the entire form or do i need to create a new thread for each individual control on the form?
Winmain.cpp
main function where I initialize the form and update the information on the form / refresh the form.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
using namespace Interface;
cooldowns ^ CDwin = gcnew cooldowns;
CDwin->Show();
CDwin->Location = Point(0,0);
while (true)
{
CDwin->timer1->Text = timer1Duration.ToString();
CDwin->timer1Progress->Value = timer1Value;
CDwin->timer1->Refresh();
CDwin->timer1Progress->Refresh();
//collect info to populate CDwin values for next cycle
//something tells me this sleep could be part of the problem?
Sleep(50);
}
}
form.h
#pragma once
namespace Interface {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Threading;
/// <summary>
/// Summary for cooldowns
/// </summary>
public ref class cooldowns : public System::Windows::Forms::Form
{
public:
cooldowns(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~cooldowns()
{
if (components)
{
delete components;
}
}
public: System::Windows::Forms::ProgressBar^ timer1Progress;
protected:
public: System::Windows::Forms::Label^ timer1;
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->timer1Progress = (gcnew System::Windows::Forms::ProgressBar());
this->timer1 = (gcnew System::Windows::Forms::Label());
this->SuspendLayout();
//
// timer1Progress
//
this->timer1Progress->ForeColor = System::Drawing::Color::Fuchsia;
this->timer1Progress->Location = System::Drawing::Point(3, 12);
this->timer1Progress->Maximum = 30000;
this->timer1Progress->Name = L"timer1Progress";
this->timer1Progress->Size = System::Drawing::Size(244, 18);
this->timer1Progress->Style = System::Windows::Forms::ProgressBarStyle::Continuous;
this->timer1Progress->TabIndex = 0;
this->timer1Progress->Value = 10000;
//
//timer1
//
this->timer1->AutoSize = true;
this->timer1->ForeColor = System::Drawing::Color::White;
this->timer1->Location = System::Drawing::Point(253, 108);
this->timer1->Name = L"Timer1";
this->timer1->Size = System::Drawing::Size(34, 13);
this->timer1->TabIndex = 9;
this->timer1->Text = L"00.00";
//
// cooldowns
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)),
static_cast<System::Int32>(static_cast<System::Byte>(64)));
this->ClientSize = System::Drawing::Size(294, 138);
this->Controls->Add(this->Timer1);;
this->Controls->Add(this->timer1Progress);
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
this->Name = L"cooldowns";
this->StartPosition = System::Windows::Forms::FormStartPosition::Manual;
this->Text = L"cooldowns";
this->TopMost = true;
this->Load += gcnew System::EventHandler(this, &cooldowns::cooldowns_Load);
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: System::Void cooldowns_Load(System::Object^ sender, System::EventArgs^ e) {
}
};
}
edit after a lot of trial and error the issue seems to surround the CDwin->Show();. if i switch it to ShowDialog(); it no longer is unresponsive, unfortunately the values of the progress bars do not update either, which i believe is where the multi-threading comes into play.
I think you should use ShowDialog so your form has a message loop, and put your "every 50 ms" stuff in an event handler listening to your timer's Tick event.
As the first form you should always use System::Windows::Forms::Application::Run(CDwin), you can only use Show() and ShowDialog() methods when you already have run a form.
if you use Run() you will encounter some problems. This functions only returns something after form is closed that means codes after the Run() code will not be run until form is closed.
So you must forget about working with your form in main function. I recommend you to create two forms for example "Form1" and "Form2" (using threads is another way but this one's easier).
Use "Form1" as the base form that is hidden and it is used for updating the application by refreshing timer.
Use "Form2" as showed form to user. For doing this you should run "Form2" inside "Form1" using Show() or ShowDialog().
So that means:
// This is Form1 or base.
#include "Form2.h"
Form2 ^openForm2 = gcnew Form2();
openForm2->Show();
// while(true) Refresh the other form and other codes...

Creating a vector of a struct in a c++ windows form

I am trying to write a program that uses a global vector of a struct in a c++ windows form. Below is the code. The commented areas are attempts I've made to create a vector. Most of them do not compile. Some of them compile, but the program will not display. I do not understand the nature of this error because I was able to create vectors of structs in command line programs. Any help would be appreciated!
#pragma once
#include <vector>
#include <cliext/vector>
namespace student_database {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form11
/// </summary>
public ref class Form11 : public System::Windows::Forms::Form
{
public:
Form11(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form11()
{
if (components)
{
delete components;
}
}
private:
ref struct student{
int index;
String^ name;
cliext::vector <String^> essays;
};
cliext::vector <student^> student_vector; // builds without errors, but program does not start
// array <student^>^ Qarray;
// static cliext::vector<student^>::generic_container^ student_vector = gcnew cliext::vector<student^>;//(0);
// cliext::vector<student^> ^c;
// c = gcnew(cliext::vector<student^>);
//cliext::vector <student> student_vector = gcnew cliext::vector <student>;
//cliext::vector<student^> ^student_vector = gcnew(cliext::vector<student^>);
// cliext::vector <student^>^ student_vector;
// Microsoft::VisualC::StlClr::Ivector<student^> ^student_vector;
// Ivector<student^> ^student_vector;
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->SuspendLayout();
//
// Form11
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(284, 262);
this->Name = L"Form11";
this->Text = L"Form11";
this->Load += gcnew System::EventHandler(this, &Form11::Form11_Load);
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void Form11_Load(System::Object^ sender, System::EventArgs^ e) {
}
};
}

Setting ToolStripDropDown.DropShadowEnabled to false on multi level dropdowns

I want to disable the dropdown shadow on the dropdown of a ToolStripDropDownButton. If the dropdown menu contains items that have dropdowns themselves (e.g. multi-level menu) then setting the DropShadowEnabled to false on the ToolStripDropDownButton causes the top level dropdown to appear at the wrong position. See attached picture.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
toolStripDropDownButton1.DropDown.DropShadowEnabled = false;
}
}
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.toolStripDropDownButton1 = new System.Windows.Forms.ToolStripDropDownButton();
this.item1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.subitem1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStrip1.SuspendLayout();
this.SuspendLayout();
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripDropDownButton1});
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(292, 25);
this.toolStrip1.TabIndex = 0;
this.toolStrip1.Text = "toolStrip1";
//
// toolStripDropDownButton1
//
this.toolStripDropDownButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.toolStripDropDownButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.item1ToolStripMenuItem});
this.toolStripDropDownButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripDropDownButton1.Image")));
this.toolStripDropDownButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripDropDownButton1.Name = "toolStripDropDownButton1";
this.toolStripDropDownButton1.Size = new System.Drawing.Size(29, 22);
this.toolStripDropDownButton1.Text = "toolStripDropDownButton1";
//
// item1ToolStripMenuItem
//
this.item1ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.subitem1ToolStripMenuItem});
this.item1ToolStripMenuItem.Name = "item1ToolStripMenuItem";
this.item1ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.item1ToolStripMenuItem.Text = "item1";
//
// subitem1ToolStripMenuItem
//
this.subitem1ToolStripMenuItem.Name = "subitem1ToolStripMenuItem";
this.subitem1ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.subitem1ToolStripMenuItem.Text = "subitem1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.toolStrip1);
this.Name = "Form1";
this.Text = "Form1";
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ToolStrip toolStrip1;
private System.Windows.Forms.ToolStripDropDownButton toolStripDropDownButton1;
private System.Windows.Forms.ToolStripMenuItem item1ToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem subitem1ToolStripMenuItem;
}
This is very typical lossage in the ToolStripItem classes. Clearly it is a bug, it probably got introduced when they applied a hack to work around a Windows problem. You can still see the internal bug number in the Reference Source:
public bool DropShadowEnabled {
get {
// VSWhidbey 338272 - DropShadows are only supported on TopMost windows
// due to the flakeyness of the way it's implemented in the OS. (Non toplevel
// windows can have parts of the shadow disappear because another window can get
// sandwiched between the SysShadow window and the dropdown.)
return dropShadowEnabled && TopMost && DisplayInformation.IsDropShadowEnabled;
}
set { // etc... }
}
But without a corresponding fix in the setter and the renderer.
The flakeyness they mentioned actually got fixed in Vista, you are still running on XP so you can't see it. Drop shadows are done differently on the Aero desktop and it is a system setting whether or not they are enabled. So using the property is entirely ineffective on Aero.
These ToolStripItem class bugs didn't get fixed after the .NET 2.0 release, about the entire Winforms team moved over to the WPF group. And they are certainly not getting fixed now, no point filing a bug at connect.microsoft.com although you are free to do so.
With the added wrinkle that the property just cannot have an effect anymore on later versions of Windows since it is now a system setting, the only logical thing to do here is to throw in the towel. Don't change the property.

error C3861: 'ShowWindow': identifier not found

I am trying to write a simple CLR-Windows Form Application. It will show a window having a button. As soon as you click the button, it will hide one of the open Windows. To achieve this I am calling ShowWindow(00050214, false );, where 00050214 is the handle of the Window I am hiding.
But it is giving error:
Error 1 error C3861: 'ShowWindow': identifier not found c:\users\afnan
\documents \visual studio 2010\projects\winformtest\winformtest\Form1.h 80
Please see the last lines of .h file given below, to see how I am using the above function.
WinformTest.cpp : main project file.
#include "stdafx.h"
#include "Form1.h"
#include"windows.h"
using namespace WinformTest;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it
Application::Run(gcnew Form1());
return 0;
}
Here is .h file
#pragma once
namespace WinformTest {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::Button^ button1;
protected:
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->button1 = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// button1
//
this->button1->Location = System::Drawing::Point(91, 51);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(75, 23);
this->button1->TabIndex = 0;
this->button1->Text = L"button1";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this,
&Form1::button1_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(284, 262);
this->Controls->Add(this->button1);
this->Name = L"Form1";
this->Text = L"Form1";
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
ShowWindow(00050214, false );
}
};
}
UPDATE
I have now put windows.h in form.h file, and used ShowWindow((HWND)0x00050214, SW_HIDE);
but now I am getting:
Error 1 error LNK2028: unresolved token (0A000011) "extern "C" int __stdcall
ShowWindow(struct HWND__ *,int)" (?ShowWindow##$$J18YGHPAUHWND__##H#Z) referenced in function
"private: void __clrcall WinformTest::Form1::button1_Click(class System::Object ^,class
System::EventArgs ^)"
(?button1_Click#Form1#WinformTest##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
C:\Users\Afnan\Documents\Visual Studio 2010\Projects\WinformTest\WinformTest\WinformTest.obj
Error 2 error LNK2019: unresolved external symbol "extern "C" int __stdcall
ShowWindow(struct HWND__ *,int)" (?ShowWindow##$$J18YGHPAUHWND__##H#Z) referenced in function
"private: void __clrcall WinformTest::Form1::button1_Click(class System::Object ^,class
System::EventArgs ^)"
(?button1_Click#Form1#WinformTest##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z)
C:\Users\Afnan\Documents\Visual Studio 2010\Projects\WinformTest\WinformTest\WinformTest.obj
Error 3 error LNK1120: 2 unresolved externals C:\Users\Afnan\Documents\Visual
Studio 2010\Projects\WinformTest\Debug\WinformTest.exe 1
How do put handle? I got this handle using spy++ tool. It also shows caption corresponding to the handle expressed in numbers. The corresponding handle in my case is: WinformTest - Microsoft Visual Studio
Your header file does not include windows.h and so the symbol ShowWindow is not known to it.
The way you call ShowWindow is also wrong. The second parameter is an int and you want to pass SW_HIDE. And I bet that your window handle is actually a hex number.
ShowWindow((HWND)0x00050214, SW_HIDE);
As an aside, I'm not sure why you put so much code in the header file. Normally you would declare the class in the header file and then define the implementation in the cpp file.

Resources