Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
So the internet says that this error means that I'm missing a ; somewhere, but as far as I can tell, I don't have that error. This code is supposed to ask the user if they want to add the word even if it's in the list already and then respond to the input accordingly. I'm average with c++ but new to GUI so I'm not familiar with all the system key words. I'm using Visual Studio 2010. And I'll give you the code with the errors and the header files included.
This is my AddName.h, Line 157 where I initialize message has the error C2143
#pragma once
#include "Generator.h"
#include <msclr/marshal_cppstd.h>
namespace GUI_PackProject {
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 msclr::interop;
/// <summary>
/// Summary for AddName
/// </summary>
public ref class AddName : public System::Windows::Forms::Form
{
public:
AddName(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~AddName()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::CheckBox^ FNCheckBox;
private: System::Windows::Forms::CheckBox^ LNCheckBox;
private: System::Windows::Forms::TextBox^ NameInput;
protected:
internal: System::Windows::Forms::Label^ UserInstruction;
private: System::Windows::Forms::Button^ btnAdd;
internal:
private:
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->FNCheckBox = (gcnew System::Windows::Forms::CheckBox());
this->LNCheckBox = (gcnew System::Windows::Forms::CheckBox());
this->NameInput = (gcnew System::Windows::Forms::TextBox());
this->UserInstruction = (gcnew System::Windows::Forms::Label());
this->btnAdd = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// FNCheckBox
//
this->FNCheckBox->AutoSize = true;
this->FNCheckBox->Location = System::Drawing::Point(122, 83);
this->FNCheckBox->Name = L"FNCheckBox";
this->FNCheckBox->Size = System::Drawing::Size(76, 17);
this->FNCheckBox->TabIndex = 0;
this->FNCheckBox->Text = L"First Name";
this->FNCheckBox->UseVisualStyleBackColor = true;
//
// LNCheckBox
//
this->LNCheckBox->AutoSize = true;
this->LNCheckBox->Location = System::Drawing::Point(121, 106);
this->LNCheckBox->Name = L"LNCheckBox";
this->LNCheckBox->Size = System::Drawing::Size(77, 17);
this->LNCheckBox->TabIndex = 1;
this->LNCheckBox->Text = L"Last Name";
this->LNCheckBox->UseVisualStyleBackColor = true;
//
// NameInput
//
this->NameInput->Location = System::Drawing::Point(122, 57);
this->NameInput->Name = L"NameInput";
this->NameInput->Size = System::Drawing::Size(100, 20);
this->NameInput->TabIndex = 2;
//
// UserInstruction
//
this->UserInstruction->AutoSize = true;
this->UserInstruction->Location = System::Drawing::Point(53, 60);
this->UserInstruction->Name = L"UserInstruction";
this->UserInstruction->Size = System::Drawing::Size(63, 13);
this->UserInstruction->TabIndex = 3;
this->UserInstruction->Text = L"New Name:";
//
// btnAdd
//
this->btnAdd->Location = System::Drawing::Point(104, 149);
this->btnAdd->Name = L"btnAdd";
this->btnAdd->Size = System::Drawing::Size(75, 23);
this->btnAdd->TabIndex = 4;
this->btnAdd->Text = L"Add!";
this->btnAdd->UseVisualStyleBackColor = true;
this->btnAdd->Click += gcnew System::EventHandler(this, &AddName::btnAdd_Click);
//
// AddName
//
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->btnAdd);
this->Controls->Add(this->UserInstruction);
this->Controls->Add(this->NameInput);
this->Controls->Add(this->LNCheckBox);
this->Controls->Add(this->FNCheckBox);
this->Name = L"AddName";
this->Text = L"AddName";
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: System::Void btnAdd_Click(System::Object^ sender, System::EventArgs^ e)
{
bool warned = false;
int duptimes1 = 0;
int duptimes2 = 0;
String^ Name = NameInput -> Text;
string name = marshal_as<std::string>(Name);
Generator Pack_Names ("FirstNames.txt", "LastNames.txt");
if (String::IsNullOrEmpty(NameInput->Text))
{
MessageBox::Show("Please Enter in a Name to Input!");
}
else if (!FNCheckBox-> Checked && !LNCheckBox-> Checked)
{
MessageBox::Show("Please Check One or Both Boxes.");
}
//add first or last name to the list, including set-ups for duplicates
System::Windows::Forms::DialogResult result;
duptimes1 = Pack_Names.CheckDupps(name, 1);
duptimes2 = Pack_Names.CheckDupps(name, 2);
String^ message = "That name is already in First Names " + duptimes1 + " times and Last Names " + duptimes2 " . Would you like to add it anyways?";
if (FNCheckBox-> Checked)
{
if (duptimes1 > 0)
{
result = MessageBox::Show(message, "Multiple Name Error", MessageBoxButtons::YesNo, MessageBoxIcon::Question);
warned = true;
if (result == System::Windows::Forms::DialogResult::Yes)
{
Pack_Names.Add(name, 1); //adds name to list 1
}
else if (result == System::Windows::Forms::DialogResult::No)
{
//close the window
}
}
else
{
Pack_Names.Add(name, 1);
}
}
if (LNCheckBox->Checked)
{
if (duptimes2 > 0 && warned == false)
{
result = MessageBox::Show(message, "Multiple Name Error", MessageBoxButtons::YesNo, MessageBoxIcon::Question);
warned = true;
if (result == System::Windows::Forms::DialogResult::Yes)
{
Pack_Names.Add(name, 2); //adds name to list 2
}
else if (result == System::Windows::Forms::DialogResult::No)
{
//close the window
}
}
else
{
Pack_Names.Add(name, 2);
}
}
//close the window
}//End btnAdd
};
}
# Generator.h file #
#pragma once
#include <string>
#include <iostream>
#include <vector>
#include <iostream>
#include <fstream>
#include <ctime>
#include "StdAfx.h"
using namespace std;
class Generator
{
public:
Generator(string file_name1, string file_name2);
~Generator();
void Delete(string word, int list);
int CheckDupps(string word, int list);
int FindName(string word, int list);
void Scramble(int list, int times);
void Show(int number);
void Add(string word, int list);
string GetFullName(int number);
void Save1(string file_name);
void Save2(string file_name);
string GetName(int place, int list);
int GetSize(int list);
void ChangeName(int list, int place, string new_name);
void Update();
private:
vector <string> First;
vector <string> Last;
string FileName1;
string FileName2;
};
Let me know if you need more information or where I can go to figure out where the problem is!
String^ message = "That name is already in First Names " + duptimes1 + " times and Last Names " + duptimes2 " . Would you like to add it anyways?";
You missed a "+" at the end there.
String^ message = "That name is already in First Names " + duptimes1 + " times and Last Names " + duptimes2 + " . Would you like to add it anyways?";
Related
I've tried using a few methods but can't seem to pass along the label to the new thread or have the secondary thread be able to access the label and refresh the form on the form thread. I'm trying to have it multi-threaded so the interface doesn't lock up when running commands to remote devices. Any help in having a way to update the label and refresh the form from a secondary thread would be appreciated! Here is my MyForm.h file and MyForm.cpp file:
#include <iostream>
#include <conio.h>
#include <windows.h>
namespace StudioControl2 {
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;
using namespace System::Threading::Tasks;
using namespace std;
bool GUIEvent = false;
/// <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: System::Windows::Forms::Button^ WindowTVVmixSelect;
private: System::Windows::Forms::Label^ StatusOutput;
private: System::ComponentModel::IContainer^ components;
protected:
private:
/// <summary>
/// Required designer variable.
/// </summary>
#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)
{
System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(MyForm::typeid));
this->WindowTVVmixSelect = (gcnew System::Windows::Forms::Button());
this->StatusOutput = (gcnew System::Windows::Forms::Label());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->pictureBox1))->BeginInit();
this->SuspendLayout();
//
// WindowTVVmixSelect
//
this->WindowTVVmixSelect->Anchor = System::Windows::Forms::AnchorStyles::None;
this->WindowTVVmixSelect->Location = System::Drawing::Point(31, 400);
this->WindowTVVmixSelect->Margin = System::Windows::Forms::Padding(5);
this->WindowTVVmixSelect->Name = L"WindowTVVmixSelect";
this->WindowTVVmixSelect->Size = System::Drawing::Size(120, 30);
this->WindowTVVmixSelect->TabIndex = 10;
this->WindowTVVmixSelect->Text = L"Vmix";
this->WindowTVVmixSelect->UseVisualStyleBackColor = true;
this->WindowTVVmixSelect->Click += gcnew System::EventHandler(this, &MyForm::WindowTVVmixSelect_Click);
//
// StatusOutput
//
this->StatusOutput->Anchor = System::Windows::Forms::AnchorStyles::None;
this->StatusOutput->BorderStyle = System::Windows::Forms::BorderStyle::Fixed3D;
this->StatusOutput->ForeColor = System::Drawing::Color::Red;
this->StatusOutput->Location = System::Drawing::Point(232, 612);
this->StatusOutput->Margin = System::Windows::Forms::Padding(5);
this->StatusOutput->Name = L"StatusOutput";
this->StatusOutput->Size = System::Drawing::Size(120, 30);
this->StatusOutput->TabIndex = 20;
this->StatusOutput->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;
//
// MyForm
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(584, 661);
this->Controls->Add(this->WindowTVVmixSelect);
this->MinimumSize = System::Drawing::Size(600, 700);
this->Name = L"MyForm";
this->Text = L"Studio Control";
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->pictureBox1))->EndInit();
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: System::Void WindowTVVmixSelect_Click(System::Object^ sender, System::EventArgs^ e) {
if (GUIEvent == false) {
GUIEvent = true;
Console::WriteLine("Window TV Vmix Select");
WindowHDMIStatus -> Text = "Vmix";
StatusOutput->Text = "Please Wait";
MyForm::Refresh();
//Creation of new thread.
ThreadWindowTVVmixSelect^ o1 = gcnew ThreadWindowTVVmixSelect();
Thread^ t1 = gcnew Thread(gcnew ThreadStart(o1, &ThreadWindowTVVmixSelect::ThreadEntryPoint));
t1->Name = "t1";
t1->Start();
}
}
ref class ThreadWindowTVVmixSelect
{
public:
void ThreadEntryPoint()
{
Sleep(2000);
Console::WriteLine("Terminating Thread Window TV Vmix Select");
//Trying to update and refresh label in MyForm.
GUIEvent = false;
}
};
};
}
#include "MyForm.h"
using namespace System;
using namespace System::Windows::Forms;
[STAThreadAttribute]
int main(array<String^>^ args) {
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
StudioControl2::MyForm form;
Application::Run(%form);
return 0;
}
As shown here MS Docs Forms Invoker
You need to create so called invoker that invokes the commands you give him in the thread that created him, so it's delegate.
Edit:
I didn't realize it's cpp, syntax is a bit different but the main idea is the same
Define and ise delegates MS Doc
I figured out how to make a Thread-Safe call from the same site I mentioned (https://learn.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls). There's a small symbol at the top right of the page (</>) that changes the code examples to one of three options, C#, VB, or C++.
Here's the code I used for setting up a new thread, and running a thread safe invoke on the form label on the UI thread from the new thread:
private:
Thread^ Thread1;
private: System::Void WindowTVVmixSelect_Click(System::Object^ sender, System::EventArgs^ e) {
if (GUIEvent == false) {
GUIEvent = true;
Console::WriteLine("Window TV Vmix Select");
StatusOutput->Text = "Please Wait";
MyForm::Refresh();
//Creation of new thread.
this->Thread1 =
gcnew Thread(gcnew ThreadStart(this, &MyForm::ThreadWindowTVVmixSelect));
this->Thread1->Start();
}
}
private:
void ThreadWindowTVVmixSelect()
{
Sleep(3000);
//SetTextWindowHDMIStatus("Vmix");
SetTextStatusOutput("");
GUIEvent = false;
}
delegate void StringArgReturningVoidDelegate(String^ text);
//Sets the status label in the form
private:
void SetTextStatusOutput(String^ text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this->StatusOutput->InvokeRequired)
{
StringArgReturningVoidDelegate^ d =
gcnew StringArgReturningVoidDelegate(this, &MyForm::SetTextStatusOutput);
this->Invoke(d, gcnew array<Object^> { text });
}
else
{
this->StatusOutput->Text = text;
}
}
Hopefully this will help anyone else looking to update a C++ CLR form from another thread.
I have created an MFC dialog based application to study tab control. In a tab control it is possible to set application specific data to each tab.
I am trying to understand how to set/retrieve the data for individual tabs of the tab control.
Here is a sample application I am creating. Each tab of the control is supposed to store some GPU info.
As I understand, there are 3 steps to add application specific data.
Create a user defined structure, whose 1st member should be of type TCITEMHEADER.
struct GPU {
std::wstring name;
int busid;
};
struct tabData {
TCITEMHEADER tabItemHeader;
GPU gpu;
};
Tell the tab control about the extra bytes, the user defined structure is going to take. This I am doing in DoDataExchange().
int extraBytes = sizeof(tabData) - sizeof(TCITEMHEADER);
auto status = tabCtrl1.SetItemExtra(extraBytes);
Set user defined data while adding tabs.
static int tabCtr = 0;
tabData td;
td.tabItemHeader.pszText = _T("TabX");
td.tabItemHeader.mask = TCIF_TEXT;
td.gpu.name = L"AMD NVIDIA";
td.gpu.busid = 101;
TabCtrl_InsertItem(tabCtrl1.GetSafeHwnd(), tabCtr, &td);
Now to get the data, we simply have to call TabCtrl_GetItem().
tabData td2;
td2.tabItemHeader.pszText = new TCHAR[20];
td2.tabItemHeader.cchTextMax = 20;
td2.tabItemHeader.mask = TCIF_TEXT;
td2.gpu.busid = 0;
TabCtrl_GetItem(tabCtrl1.GetSafeHwnd(), 0, &td2);
But as we can see in the following image. I do get the tab text (pszText member - data Item 1 in image), but not the extra data that I had associated with it previously (Data Items 2 and 3 in image).
Which step am I missing?
Why is the structure associated with application defined data not getting populated?
Additional Info
Here is the complete code for the application.
CPP File:
// tabCtrlStackOverflowDlg.cpp : implementation file
//
#include "stdafx.h"
#include "tabCtrlStackOverflow.h"
#include "tabCtrlStackOverflowDlg.h"
#include "afxdialogex.h"
#include <string>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
struct GPU {
std::wstring name;
int busid;
};
struct tabData
{
TCITEMHEADER tabItemHeader;
GPU gpu;
};
CtabCtrlStackOverflowDlg::CtabCtrlStackOverflowDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_TABCTRLSTACKOVERFLOW_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CtabCtrlStackOverflowDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TAB1, tabCtrl1);
int extraBytes = sizeof(tabData) - sizeof(TCITEMHEADER);
auto status = tabCtrl1.SetItemExtra(extraBytes);
wchar_t *t = status ? L"SetItemExtra() success" : L"SetItemExtra() fail";
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(t);
}
BEGIN_MESSAGE_MAP(CtabCtrlStackOverflowDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDADDTAB, &CtabCtrlStackOverflowDlg::OnBnClickedAddtab)
ON_BN_CLICKED(IDC_GETITEM0, &CtabCtrlStackOverflowDlg::OnBnClickedGetitem0)
ON_BN_CLICKED(IDCLOSE, &CtabCtrlStackOverflowDlg::OnBnClickedClose)
END_MESSAGE_MAP()
// CtabCtrlStackOverflowDlg message handlers
BOOL CtabCtrlStackOverflowDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CtabCtrlStackOverflowDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CtabCtrlStackOverflowDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CtabCtrlStackOverflowDlg::OnBnClickedAddtab()
{
static int tabCtr = 0;
tabData td;
td.tabItemHeader.pszText = _T("TabX");
td.tabItemHeader.mask = TCIF_TEXT;
td.gpu.name = L"AMD NVIDIA";
td.gpu.busid = 101;
int status = TabCtrl_InsertItem(tabCtrl1.GetSafeHwnd(), tabCtr, &td);
wchar_t *t = L"";
if (status == -1)
{
t = L"TabCtrl_InsertItem() Fail";
}
else
{
t = L"TabCtrl_InsertItem() success";
}
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(t);
tabCtr++;
}
void CtabCtrlStackOverflowDlg::OnBnClickedGetitem0()
{
tabData td2;
td2.tabItemHeader.pszText = new TCHAR[20];
td2.tabItemHeader.cchTextMax = 20;
td2.tabItemHeader.mask = TCIF_TEXT;
td2.gpu.busid = 0;
if (TabCtrl_GetItem(tabCtrl1.GetSafeHwnd(), 0, &td2) == TRUE)
{
std::wstring text = td2.tabItemHeader.pszText;
text += std::wstring(L" ") + td2.gpu.name;
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(text.c_str());
}
else
{
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(_T("TabCtrl_GetItem()
error"));
}
}
void CtabCtrlStackOverflowDlg::OnBnClickedClose()
{
CDialog::OnCancel();
}
Header File:
// tabCtrlStackOverflowDlg.h : header file
//
#pragma once
#include "afxcmn.h"
// CtabCtrlStackOverflowDlg dialog
class CtabCtrlStackOverflowDlg : public CDialogEx
{
// Construction
public:
CtabCtrlStackOverflowDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TABCTRLSTACKOVERFLOW_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CTabCtrl tabCtrl1;
afx_msg void OnBnClickedAddtab();
afx_msg void OnBnClickedGetitem0();
afx_msg void OnBnClickedClose();
};
Solution Summary
From Barmak Shemirani's answer here are the 3 reasons my code wasn't working. Must read his answer for better understanding.
TCIF_PARAM must be set in mask, while doing TCM_INSERTITEM, and TCM_GETITEM.
I was using local variables created on stack (tabData td2; object). The reference to this variable was becoming invalid as soon as it was going out of scope.
Using std::wstring in the structure being used for TCM_INSERTITEM. It is better to use data types whose size can be accurately be determined (like plain old data types.).
As Barmak Shemirani points out in comments, the documentation for TCITEMHEADER is scarce. His answer provides a thorough explanation.
Conflict with documentation
Documentation for TCITEMHEADER does not mention using TCIF_PARAM flag. Maybe that's a mistake in documention!
It's better if SetItemExtra is moved to OnInitDialog after default procedure is called. This ensures SetItemExtra is called only once when control is empty.
The structure GPU has a std::wstring member whose data size is unknown at the start. TCM_INSERTITEM cannot make a copy of this data unless you have a simple POD structure.
To store the data in the tab, replace std::wstring with wchar_t name[100] so that data is a simple POD structure with fixed size.
struct GPU
{
//std::wstring name;
wchar_t name[100];
int busid;
};
struct tabData
{
TCITEMHEADER tabItemHeader;
GPU gpu;
};
void CMyDialog::OnBnClickedAddtab()
{
int index = tab.GetItemCount();
wchar_t tabname[50];
wsprintf(tabname, L"Tab %d", index);
tabData sdata = { 0 };
sdata.tabItemHeader.mask = TCIF_TEXT | TCIF_PARAM;
sdata.tabItemHeader.pszText = tabname;
wsprintf(sdata.gpu.name, L"AMD NVIDIA %d", index);
sdata.gpu.busid = 101;
tab.SendMessage(TCM_INSERTITEM, index, (LPARAM)(TCITEMHEADER*)(&sdata));
}
void CMyDialog::OnBnClickedGetitem0()
{
int index = tab.GetCurSel();
tabData data = { 0 };
wchar_t buf[20] = { 0 };
data.tabItemHeader.pszText = buf;
data.tabItemHeader.cchTextMax = sizeof(buf)/sizeof(wchar_t);
data.tabItemHeader.mask = TCIF_TEXT | TCIF_PARAM;
if(tab.SendMessage(TCM_GETITEM, index, (LPARAM)(TCITEMHEADER*)(&data)))
{
CString str;
str.Format(L"%d %s", data.gpu.busid, data.gpu.name);
GetDlgItem(IDC_STATIC1)->SetWindowText(str);
}
}
Alternative method:
If std::wstring name; cannot be replaced with wchar_t buffer, we have to define a separate permanent data, for example using std::vector. Then we use the lParam value in TCITEM to point to the vector.
This method only needs the standard 4 bytes of lParam, it doesn't require TCITEMHEADER and SetItemExtra. You can even define std::vector<GPU>. Example:
std::vector<tabData> m_data;
BOOL CMyDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
tabData data;
data.gpu.name = L"AMD NVIDIA1";
data.gpu.busid = 101;
m_data.push_back(data);
data.gpu.name = L"AMD NVIDIA2";
data.gpu.busid = 102;
m_data.push_back(data);
return TRUE;
}
void CMyDialog::OnBnClickedAddtab()
{
static int tabCtr = 0;
if(tabCtr >= (int)m_data.size())
return;
TCITEM item = { 0 };
item.pszText = _T("TabX");
item.mask = TCIF_TEXT | TCIF_PARAM;
item.lParam = (LPARAM)&m_data[tabCtr];
tab.InsertItem(tabCtr, &item);
tabCtr++;
}
void CMyDialog::OnBnClickedGetitem0()
{
TCITEM item = { 0 };
item.mask = TCIF_TEXT | TCIF_PARAM;
if(tab.GetItem(tab.GetCurSel(), &item) == TRUE)
{
tabData* ptr = (tabData*)item.lParam;
CString str;
str.Format(L"%d %s", ptr->gpu.busid, ptr->gpu.name.c_str());
GetDlgItem(IDC_STATIC1)->SetWindowText(str);
}
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
#pragma once
namespace StudentDataSearch {
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^ btnSearch;
protected:
protected:
private: System::Windows::Forms::Label^ Course_ID1;
protected:
private: System::Windows::Forms::TextBox^ txtTargetID;
private: System::Windows::Forms::GroupBox^ groupBox1;
private: System::Windows::Forms::TextBox^ txtSeats;
private: System::Windows::Forms::Label^ Seats;
private: System::Windows::Forms::TextBox^ txtID;
private: System::Windows::Forms::Label^ Course_ID;
private: System::Windows::Forms::TextBox^ txtName;
private: System::Windows::Forms::Label^ Course_Names2;
private: System::Windows::Forms::Button^ btnSearchName;
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->btnSearch = (gcnew System::Windows::Forms::Button());
this->Course_ID1 = (gcnew System::Windows::Forms::Label());
this->txtTargetID = (gcnew System::Windows::Forms::TextBox());
this->groupBox1 = (gcnew System::Windows::Forms::GroupBox());
this->txtSeats = (gcnew System::Windows::Forms::TextBox());
this->Seats = (gcnew System::Windows::Forms::Label());
this->txtID = (gcnew System::Windows::Forms::TextBox());
this->Course_ID = (gcnew System::Windows::Forms::Label());
this->txtName = (gcnew System::Windows::Forms::TextBox());
this->Course_Names2 = (gcnew System::Windows::Forms::Label());
this->btnSearchName = (gcnew System::Windows::Forms::Button());
this->groupBox1->SuspendLayout();
this->SuspendLayout();
//
// btnSearch
//
this->btnSearch->Location = System::Drawing::Point(12, 12);
this->btnSearch->Name = L"btnSearch";
this->btnSearch->Size = System::Drawing::Size(144, 39);
this->btnSearch->TabIndex = 0;
this->btnSearch->Text = L"Search by Course ID";
this->btnSearch->UseVisualStyleBackColor = true;
this->btnSearch->Click += gcnew System::EventHandler(this, &Form1::btnSearch_Click);
//
// Course_ID1
//
this->Course_ID1->AutoSize = true;
this->Course_ID1->Location = System::Drawing::Point(317, 28);
this->Course_ID1->Name = L"Course_ID1";
this->Course_ID1->Size = System::Drawing::Size(54, 13);
this->Course_ID1->TabIndex = 1;
this->Course_ID1->Text = L"Course ID";
//
// txtTargetID
//
this->txtTargetID->Location = System::Drawing::Point(377, 25);
this->txtTargetID->Name = L"txtTargetID";
this->txtTargetID->Size = System::Drawing::Size(100, 20);
this->txtTargetID->TabIndex = 2;
//
// groupBox1
//
this->groupBox1->Controls->Add(this->txtSeats);
this->groupBox1->Controls->Add(this->Seats);
this->groupBox1->Controls->Add(this->txtID);
this->groupBox1->Controls->Add(this->Course_ID);
this->groupBox1->Controls->Add(this->txtName);
this->groupBox1->Controls->Add(this->Course_Names2);
this->groupBox1->Location = System::Drawing::Point(12, 145);
this->groupBox1->Name = L"groupBox1";
this->groupBox1->Size = System::Drawing::Size(465, 140);
this->groupBox1->TabIndex = 3;
this->groupBox1->TabStop = false;
this->groupBox1->Text = L"Search Results";
//
// txtSeats
//
this->txtSeats->Location = System::Drawing::Point(301, 81);
this->txtSeats->Name = L"txtSeats";
this->txtSeats->Size = System::Drawing::Size(100, 20);
this->txtSeats->TabIndex = 5;
//
// Seats
//
this->Seats->AutoSize = true;
this->Seats->Location = System::Drawing::Point(298, 65);
this->Seats->Name = L"Seats";
this->Seats->Size = System::Drawing::Size(34, 13);
this->Seats->TabIndex = 4;
this->Seats->Text = L"Seats";
//
// txtID
//
this->txtID->Location = System::Drawing::Point(204, 81);
this->txtID->Name = L"txtID";
this->txtID->Size = System::Drawing::Size(91, 20);
this->txtID->TabIndex = 3;
//
// Course_ID
//
this->Course_ID->AutoSize = true;
this->Course_ID->Location = System::Drawing::Point(206, 65);
this->Course_ID->Name = L"Course_ID";
this->Course_ID->Size = System::Drawing::Size(54, 13);
this->Course_ID->TabIndex = 2;
this->Course_ID->Text = L"Course ID";
//
// txtName
//
this->txtName->Location = System::Drawing::Point(25, 81);
this->txtName->Name = L"txtName";
this->txtName->Size = System::Drawing::Size(173, 20);
this->txtName->TabIndex = 1;
//
// Course_Names2
//
this->Course_Names2->AutoSize = true;
this->Course_Names2->Location = System::Drawing::Point(22, 65);
this->Course_Names2->Name = L"Course_Names2";
this->Course_Names2->Size = System::Drawing::Size(71, 13);
this->Course_Names2->TabIndex = 0;
this->Course_Names2->Text = L"Course Name";
//
// btnSearchName
//
this->btnSearchName->Location = System::Drawing::Point(12, 57);
this->btnSearchName->Name = L"btnSearchName";
this->btnSearchName->Size = System::Drawing::Size(144, 39);
this->btnSearchName->TabIndex = 4;
this->btnSearchName->Text = L"Search by Course Name";
this->btnSearchName->UseVisualStyleBackColor = true;
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(519, 297);
this->Controls->Add(this->btnSearchName);
this->Controls->Add(this->groupBox1);
this->Controls->Add(this->txtTargetID);
this->Controls->Add(this->Course_ID1);
this->Controls->Add(this->btnSearch);
this->Name = L"Form1";
this->Text = L"Student Data Search";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->groupBox1->ResumeLayout(false);
this->groupBox1->PerformLayout();
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: array<String^>^ CourseArr;
private: array<String^>^ CourseID;
private: array<Int32>^ SeatsArr;
private: String^ strTarget;
private: String^ strOut;
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
// Course Names
CourseArr = gcnew array<String^>(9);
CourseArr->SetValue("Computer Sci 1511", 0);
CourseArr->SetValue("Computer Sci 1521", 1);
CourseArr->SetValue("Composition 1120", 2);
CourseArr->SetValue("Math 1296", 3);
CourseArr->SetValue("Physics 1120", 4);
CourseArr->SetValue("Biology 1100", 5);
CourseArr->SetValue("Chemistry 1100", 6);
CourseArr->SetValue("Anthropology 1210", 7);
CourseArr->SetValue("Economics 1000", 8);
// Course ID
CourseID = gcnew array<String^>(9);
CourseID->SetValue("123", 0);
CourseID->SetValue("124", 1);
CourseID->SetValue("135", 2);
CourseID->SetValue("145", 3);
CourseID->SetValue("146", 4);
CourseID->SetValue("149", 5);
CourseID->SetValue("155", 6);
CourseID->SetValue("162", 7);
CourseID->SetValue("175", 8);
//Seats Avaliable
SeatsArr = gcnew array<Int32>(9);
SeatsArr->SetValue(0, 0);
SeatsArr->SetValue(25, 1);
SeatsArr->SetValue(14, 2);
SeatsArr->SetValue(5, 3);
SeatsArr->SetValue(0, 4);
SeatsArr->SetValue(20, 5);
SeatsArr->SetValue(17, 6);
SeatsArr->SetValue(0, 7);
SeatsArr->SetValue(12, 8);
}
private: System::Void btnSearch_Click(System::Object^ sender, System::EventArgs^ e) {
int course, small, large;
int id;
int seats;
small = 0;
large = 9;
strTarget = txtTargetID->Text;
if (strTarget == "")
{
MessageBox::Show("Fill in empty fields");
return;
}
help needed here ----------------------------------------------------------
I need to loop through my arrays and used their values (listed above) and put the selected values into certain text boxes but I am unsure if I need another for loop or what please help and all help is appreciated.
for (int small = 0; small <= large; small++)
{
for (int course = 0; course < CourseID->Length; course++)
{
txtName->Text = CourseArr[0];
txtID->Text = CourseID[0];
txtSeats->Text = SeatsArr[0].ToString();
}
}
Referring to CourseArr[0] etc. within the loop will give you the same element each time.
You need to refer to CourseArr[course].
(I suspect this isn't enough to solve your problem, but it's hard to figure out what's required for that!)
I'm writing a program that includes a secondary form using C++/CLI in Visual Studio 2005. So far, I haven't progressed much due to a pair of redefinition errors that don't make much sense.
Mode.h(12) : error C2374: 'NameManipulator::check' : redefinition; multiple initialization
Mode.h(12) : see declaration of 'NameManipulator::check'
Mode.h(22) : error C2011: 'NameManipulator::Mode' : 'class' type redefinition
Mode.h(22) : see declaration of 'NameManipulator::Mode'
I've only declared each of these once, in just one namespace. One was even pre-generated by the compiler. Is there anything I can do to fix this besides starting from scratch? Any help would be much appreciated. (Code below)
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
namespace NameManipulator {
int check = 4;
/// <summary>
/// Summary for Mode
///
/// WARNING: If you change the name of this class, you will need to change the
/// 'Resource File Name' property for the managed resource compiler tool
/// associated with all .resx files this class depends on. Otherwise,
/// the designers will not be able to interact properly with localized
/// resources associated with this form.
/// </summary>
public ref class Mode : public System::Windows::Forms::Form
{
public:
Mode(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Mode()
{
if (components)
{
delete components;
}
}
public: System::Windows::Forms::RadioButton^ rdoAllCaps;
public: System::Windows::Forms::RadioButton^ rdoAllLow;
public: System::Windows::Forms::RadioButton^ rdoReverse;
public: System::Windows::Forms::RadioButton^ rdoNormal;
private: System::Windows::Forms::Button^ btnOK;
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->rdoAllCaps = (gcnew System::Windows::Forms::RadioButton());
this->rdoAllLow = (gcnew System::Windows::Forms::RadioButton());
this->rdoReverse = (gcnew System::Windows::Forms::RadioButton());
this->rdoNormal = (gcnew System::Windows::Forms::RadioButton());
this->btnOK = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// rdoAllCaps
//
this->rdoAllCaps->AutoSize = true;
this->rdoAllCaps->Location = System::Drawing::Point(12, 12);
this->rdoAllCaps->Name = L"rdoAllCaps";
this->rdoAllCaps->Size = System::Drawing::Size(75, 17);
this->rdoAllCaps->TabIndex = 0;
this->rdoAllCaps->Text = L"ALL CAPS";
this->rdoAllCaps->UseVisualStyleBackColor = true;
//
// rdoAllLow
//
this->rdoAllLow->AutoSize = true;
this->rdoAllLow->Location = System::Drawing::Point(12, 35);
this->rdoAllLow->Name = L"rdoAllLow";
this->rdoAllLow->Size = System::Drawing::Size(63, 17);
this->rdoAllLow->TabIndex = 1;
this->rdoAllLow->Text = L"all lower";
this->rdoAllLow->UseVisualStyleBackColor = true;
this->rdoAllLow->CheckedChanged += gcnew System::EventHandler(this, &Mode::rdoAllLow_CheckedChanged);
//
// rdoReverse
//
this->rdoReverse->AutoSize = true;
this->rdoReverse->Location = System::Drawing::Point(12, 58);
this->rdoReverse->Name = L"rdoReverse";
this->rdoReverse->Size = System::Drawing::Size(71, 17);
this->rdoReverse->TabIndex = 2;
this->rdoReverse->Text = L"rEVERSE";
this->rdoReverse->UseVisualStyleBackColor = true;
this->rdoReverse->CheckedChanged += gcnew System::EventHandler(this, &Mode::rdoReverse_CheckedChanged);
//
// rdoNormal
//
this->rdoNormal->AutoSize = true;
this->rdoNormal->Checked = true;
this->rdoNormal->Location = System::Drawing::Point(12, 81);
this->rdoNormal->Name = L"rdoNormal";
this->rdoNormal->Size = System::Drawing::Size(73, 17);
this->rdoNormal->TabIndex = 3;
this->rdoNormal->TabStop = true;
this->rdoNormal->Text = L"rdoNormal";
this->rdoNormal->UseVisualStyleBackColor = true;
//
// btnOK
//
this->btnOK->DialogResult = System::Windows::Forms::DialogResult::OK;
this->btnOK->Location = System::Drawing::Point(32, 106);
this->btnOK->Name = L"btnOK";
this->btnOK->Size = System::Drawing::Size(33, 23);
this->btnOK->TabIndex = 4;
this->btnOK->Text = L"OK";
this->btnOK->UseVisualStyleBackColor = true;
//
// Mode
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(99, 138);
this->ControlBox = false;
this->Controls->Add(this->btnOK);
this->Controls->Add(this->rdoNormal);
this->Controls->Add(this->rdoReverse);
this->Controls->Add(this->rdoAllLow);
this->Controls->Add(this->rdoAllCaps);
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedSingle;
this->Name = L"Mode";
this->StartPosition = System::Windows::Forms::FormStartPosition::CenterParent;
this->Text = L"Mode";
this->Load += gcnew System::EventHandler(this, &Mode::Mode_Load);
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: System::Void rdoReverse_CheckedChanged(System::Object^ sender, System::EventArgs^ e){
if (rdoReverse->Checked == true)
check = 3;
}
private: System::Void Mode_Load(System::Object^ sender, System::EventArgs^ e) {
}
private: System::Void rdoAllLow_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
}
};
}
Your error is that you define the check variable in the header file:
namespace NameManipulator {
int check = 4;
// Error in the line above
Change it to a declaration, as this:
namespace NameManipulator {
extern int check;
and add the definition in a source file:
int NameManipulator::check = 4;
When you are using several modules (files of .h and .cpp) redefinition errors may occus for simple things such as a typo. The mistake I had was the following:
#ifndef NAMESPACE_FILENAME_H
#define NAMESPACE_FILEMANE_H
#include <iostream>
#include "helperFile.h"
/* you code and stuff here */
#endif
We use the #ifndef and #endif so the compiler can ignore multiple declaration on different files and only have 1 instance of definition. Now if you go back to the second line of my declarations. I made a typo fileMane instead of filename. The compiler will through so many erorrs except for this in ur way. So yeah look out for typos!
PS: lesson cost: 5 hrs of going through my code with a fine tooth comb.
Having Enable Unity (JUMBO) Build set to YES can also cause this error to occur if multiple project source files have global variables with the same name.
Here is the situation...
I am using Visual C++ 2010 Express.
I am trying to create a windows forms application that can load the source code of any given URL into a RichTextBox. I wish to accomplish this using the cUrl library. The good news is, after beating my brains out for more than 24 hours on how to properly link the libcurl.dll file to my project I was successful. In fact I was able to use the cUrl library to retrieve the source of a url in a Windows console application and print the result to a command window. So I do not have linking problems.
For reference, below is the source code for the main CPP file for the working test console app:
// MyApplication.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <curl/curl.h>
using namespace std;
int writer(char *data, size_t size, size_t nmemb, string *buffer);
string curl_httpget(const string &url);
int main(int argc, char *argv[])
{
cout << curl_httpget("http://www.google.com/") << endl;
}
string curl_httpget(const string &url)
{
string buffer;
CURL *curl;
CURLcode result;
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, url.c_str() );
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
result = curl_easy_perform(curl);//http get performed
curl_easy_cleanup(curl);//must cleanup
//error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html
if (result == CURLE_OK)
{
return buffer;
}
//curl_easy_strerror was added in libcurl 7.12.0
//cerr << "error: " << result << " " << curl_easy_strerror(result) <<endl;
return "";
}
cerr << "error: could not initalize curl" << endl;
return "";
}
int writer(char *data, size_t size, size_t nmemb, string *buffer)
{
int result = 0;
if (buffer != NULL)
{
buffer->append(data, size * nmemb);
result = size * nmemb;
}
return result;
}
Below is the code for my main project CPP file for my Windows Forms Application "Code Viewer". The includes work fine here. I setup all the necessary paths for include and lib, etc. I am compiling with /CLR (not pure):
// CodeViewer.cpp : main project file.
#include "stdafx.h"
#include "Form1.h"
#include <stdio.h>
#include <iostream>
#include <string>
#include <curl/curl.h>
using namespace CodeViewer;
[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;
}
Below is the code of my Form1.h for the "Code Viewer" app:
#include <stdio.h>
#include <iostream>
#include <string>
#include <curl/curl.h>
#pragma once
namespace CodeViewer {
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 std;
/// <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::RichTextBox^ OutputBox;
protected:
private: System::Windows::Forms::TextBox^ AddressBar;
private: System::Windows::Forms::Button^ btnGo;
protected:
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
//My variables
private:
System::String^ iAddress;
System::String^ iSource;
#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->OutputBox = (gcnew System::Windows::Forms::RichTextBox());
this->AddressBar = (gcnew System::Windows::Forms::TextBox());
this->btnGo = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// OutputBox
//
this->OutputBox->Location = System::Drawing::Point(12, 80);
this->OutputBox->Name = L"OutputBox";
this->OutputBox->Size = System::Drawing::Size(640, 228);
this->OutputBox->TabIndex = 1;
this->OutputBox->Text = L"";
//
// AddressBar
//
this->AddressBar->Location = System::Drawing::Point(12, 52);
this->AddressBar->Name = L"AddressBar";
this->AddressBar->Size = System::Drawing::Size(593, 22);
this->AddressBar->TabIndex = 2;
this->AddressBar->TextChanged += gcnew System::EventHandler(this, &Form1::AddressBar_TextChanged);
//
// btnGo
//
this->btnGo->Location = System::Drawing::Point(611, 51);
this->btnGo->Name = L"btnGo";
this->btnGo->Size = System::Drawing::Size(41, 23);
this->btnGo->TabIndex = 3;
this->btnGo->Text = L"GO";
this->btnGo->UseVisualStyleBackColor = true;
this->btnGo->Click += gcnew System::EventHandler(this, &Form1::btnGo_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(8, 16);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(664, 320);
this->Controls->Add(this->btnGo);
this->Controls->Add(this->AddressBar);
this->Controls->Add(this->OutputBox);
this->Name = L"Form1";
this->Text = L"Code Viewer 0.0.0.1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: System::Void MarshalString ( System::String^ s, std::string& os )
{
using namespace System::Runtime::InteropServices;
const char* chars = (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
os = chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
}
private: System::String^ curl_httpget(const string &url)
{
System::String^ buffer;
CURL *curl;
CURLcode result;
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, url.c_str() );
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
result = curl_easy_perform(curl);//http get performed
curl_easy_cleanup(curl);//must cleanup
//error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html
if (result == CURLE_OK)
{
return buffer;
}
//curl_easy_strerror was added in libcurl 7.12.0
//cerr << "error: " << result << " " << curl_easy_strerror(result) <<endl;
return "";
}
cerr << "error: could not initalize curl" << endl;
return "";
}
private: int writer(char *data, size_t size, size_t nmemb, string *buffer)
{
int result = 0;
if (buffer != NULL)
{
buffer->append(data, size * nmemb);
result = size * nmemb;
}
return result;
}
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
}
private: System::Void btnGo_Click(System::Object^ sender, System::EventArgs^ e) {
std::string myAddress = "";
MarshalString(iAddress, myAddress);
iSource = curl_httpget(myAddress);
OutputBox->Text = iSource;
}
private: System::Void AddressBar_TextChanged(System::Object^ sender, System::EventArgs^ e) {
iAddress = AddressBar->Text;
}
};
}
I am brand new to C++ and I am just learning how to build Windows Forms Applications so basically I don't know what the heck I'm doing. I need to be able to call these cUrl functions from inside the Form1.h and I have no idea how to do this. I want the "GO" button to execute a function call to retrieve the HTML source code of the URL typed into AddressBar using cUrl. I have probably done in excess of 100 Google searches trying to figure this one out and I am hitting the wall. I've been searching stackoverflow with the same results. Always sorta kinda close but not what I'm looking for. I'm sure there must be a way to do this.
Please be detailed in the response. I probably won't understand a technical explanation that does not include some sample source code.
Thanks very much in advance!
UPDATE: After some more tinkering and tweeking of this code on the advice of Seth (see comments below) I was able to get my code nearly functional. See the above edited version of Form1.h. I still have one remaining compiler error, but I think I am close to understanding why I have that error. Following is that error code:
c:\project\libcurl\visualstudio\codeviewer\codeviewer\Form1.h(137): error C3867: 'CodeViewer::Form1::writer': function call missing argument list; use '&CodeViewer::Form1::writer' to create a pointer to member
While my console app had no problem with this code it appears that calling the writer() function without parameters is a problem here. Right now I'm guessing the solution is to feed it the parameters that it wants, but until I try that I won't know. It's late so I'm going to bed. Tomorrow I'll research the parameters needed for the CURLOPT_WRITEFUNCTION...
SOLVED!!! ;))) WOOHOO!! See solution below (Form1.h):
#include <stdio.h>
#include <iostream>
#include <string>
#include <curl/curl.h>
using namespace std;
int writer(char *data, size_t size, size_t nmemb, string *buffer);
string curl_httpget(const string &url);
string iAddress;
string iSource;
string curl_httpget(const string &url)
{
string buffer;
CURL *curl;
CURLcode result;
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, url.c_str() );
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
result = curl_easy_perform(curl);//http get performed
curl_easy_cleanup(curl);//must cleanup
//error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html
if (result == CURLE_OK)
{
return buffer;
}
//curl_easy_strerror was added in libcurl 7.12.0
//cerr << "error: " << result << " " << curl_easy_strerror(result) <<endl;
return "";
}
cerr << "error: could not initalize curl" << endl;
return "";
}
int writer(char *data, size_t size, size_t nmemb, string *buffer)
{
int result = 0;
if (buffer != NULL)
{
buffer->append(data, size * nmemb);
result = size * nmemb;
}
return result;
}
#pragma once
namespace CodeViewer {
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::RichTextBox^ OutputBox;
protected:
private: System::Windows::Forms::TextBox^ AddressBar;
private: System::Windows::Forms::Button^ btnGo;
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->OutputBox = (gcnew System::Windows::Forms::RichTextBox());
this->AddressBar = (gcnew System::Windows::Forms::TextBox());
this->btnGo = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// OutputBox
//
this->OutputBox->Location = System::Drawing::Point(12, 80);
this->OutputBox->Name = L"OutputBox";
this->OutputBox->Size = System::Drawing::Size(640, 228);
this->OutputBox->TabIndex = 1;
this->OutputBox->Text = L"";
//
// AddressBar
//
this->AddressBar->Location = System::Drawing::Point(12, 52);
this->AddressBar->Name = L"AddressBar";
this->AddressBar->Size = System::Drawing::Size(593, 22);
this->AddressBar->TabIndex = 2;
this->AddressBar->TextChanged += gcnew System::EventHandler(this, &Form1::AddressBar_TextChanged);
//
// btnGo
//
this->btnGo->Location = System::Drawing::Point(611, 51);
this->btnGo->Name = L"btnGo";
this->btnGo->Size = System::Drawing::Size(41, 23);
this->btnGo->TabIndex = 3;
this->btnGo->Text = L"GO";
this->btnGo->UseVisualStyleBackColor = true;
this->btnGo->Click += gcnew System::EventHandler(this, &Form1::btnGo_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(8, 16);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(664, 320);
this->Controls->Add(this->btnGo);
this->Controls->Add(this->AddressBar);
this->Controls->Add(this->OutputBox);
this->Name = L"Form1";
this->Text = L"Code Viewer 0.0.0.1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: System::Void MarshalString ( System::String^ s, std::string& os )
{
using namespace System::Runtime::InteropServices;
const char* chars = (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
os = chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
}
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
}
private: System::Void btnGo_Click(System::Object^ sender, System::EventArgs^ e) {
iSource = curl_httpget(iAddress);
String^ mySource = gcnew String(iSource.c_str());
OutputBox->Text = mySource;
}
private: System::Void AddressBar_TextChanged(System::Object^ sender, System::EventArgs^ e) {
System::String^ myAddress = AddressBar->Text;
MarshalString(myAddress, iAddress);
}
};
}
As Seth stated above, I needed to move the CURL functions outside of the form class. Then I had a string type problem because the CURL functions return a std::string and I needed the string to be a System::String^ for the form class. The solution there was to use the MarshalString() function to convert the string retrieved by my CURL function from std::string to System::String^ before passing the value to OutputBox->Text. The same also holds true for AddressBar->Text. The solution above accomplishes all that and compiles clean with no errors or warnings. Also the program does exactly what I expected it to do. :)