attach ActiveX into win32 application - c++

i create win32 application and i want to attach an ActiveX into so i proceed like this
#include "stdafx.h"
#include "test.h"
#include <Windows.h>
#include <iostream>
#include <exdisp.h>
#using <System.dll>
using namespace std;
using namespace System;
// Constants
namespace {
TCHAR * windowClassName = TEXT("win32host");
TCHAR * windowTitle = TEXT("Win32 interface");
int windowWidth = 600;
int windowHeight = 600;
}
HWND container;
LRESULT CALLBACK WindowProc( HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam )
{
switch(messg)
{
case WM_SIZE:
// Redimensionnement du conteneur quand la taille de la fenêtre change:
MoveWindow(container,0,0,LOWORD(lParam), HIWORD(lParam),1);
break;
case WM_CLOSE:
// Détruire la fenêtre principale:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
// Envoyer le message de sortie du programme:
PostQuitMessage( 0 );
break;
default:
//Retour:
return( DefWindowProc( hWnd, messg, wParam, lParam ) );
}
return 0;
}
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// Register our Window class
WNDCLASS wndclass;
wndclass.style = CS_VREDRAW | CS_HREDRAW;
wndclass.lpfnWndProc = &WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = NULL;
wndclass.hbrBackground = reinterpret_cast <HBRUSH> (COLOR_BTNFACE + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName =windowClassName;
::RegisterClass(&wndclass);
// Create our main, raw win32 API window
// We create the window invisible (meaning that we do not provide WS_VISIBLE as the window style parameter), because making it visible and then
// adding a HwndSource will make it flicker.
HWND mainWindow = ::CreateWindow(
windowClassName,
windowTitle,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
windowWidth,
windowHeight,
NULL,
NULL,
hInstance,
0);
::ShowWindow (mainWindow, nCmdShow);
::UpdateWindow( mainWindow );
//ocx
typedef HRESULT (WINAPI *PFonc)(IUnknown*, HWND,IUnknown**);
HINSTANCE hDLL2 = ::LoadLibrary(TEXT("atl.dll"));
if (!hDLL2)
return 1;
//PAttachControl AtlAxAttachControl = (PAttachControl) GetProcAddress(hDLL2, (LPCSTR)"AtlAxAttachControl");
PFonc AtlAxAttachControl = (PFonc) ::GetProcAddress(hDLL2,"AtlAxAttachControl");
CLSID clsid = GetClsid();
IID DIID__DLiveX = GetDIID__DLiveX();
RECT rect;
::GetClientRect(mainWindow,&rect);
container = ::CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT",L"",WS_CHILD | WS_VISIBLE,100,100,rect.right,rect.bottom,mainWindow,0,hInstance,0);
HRESULT hr = ::CoInitialize(0);
IWebBrowser2 *pIwb;
IUnknown* unkn;
hr = ::CoCreateInstance(CLSID_WebBrowser,0,CLSCTX_ALL,IID_IWebBrowser2,(void**)&pIwb);
hr = AtlAxAttachControl(pIwb,container,0);
if(FAILED(hr)){
MessageBox(0, L"FAILED(AtlAxAttachControl(pitd, container, NULL))", L"Error", MB_ICONERROR | MB_OK);
}
pIwb->GoHome();
pIwb->Navigate2((VARIANT*)L"www.google.com",0,0,0,0);
// Start message processing
::MSG message;
while (::GetMessageA(&message, 0, 0, 0)) {
switch (message.message) {
case WM_QUIT:
break;
default:
::TranslateMessage(& message);
::DispatchMessage(& message);
break;
}
}
CoUninitialize();
FreeLibrary(hDLL2);
return 0;
}
but the when i execute my programme i got two window, one my originale empty and the Activex in another wind,
Thanks.

I have made small changes and it compiles and shows only one window with an ActiveX included:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <comdef.h>
#include <exdisp.h>
#include <oledlg.h>
using namespace std;
// Constants
namespace {
TCHAR * windowClassName = TEXT("win32host");
TCHAR * windowTitle = TEXT("Win32 interface");
int windowWidth = 600;
int windowHeight = 600;
}
HWND container;
LRESULT CALLBACK WindowProc( HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam )
{
switch(messg)
{
case WM_SIZE:
// Redimensionnement du conteneur quand la taille de la fenêtre change:
MoveWindow(container,0,0,LOWORD(lParam), HIWORD(lParam),1);
break;
case WM_CLOSE:
// Détruire la fenêtre principale:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
// Envoyer le message de sortie du programme:
PostQuitMessage( 0 );
break;
default:
//Retour:
return( DefWindowProc( hWnd, messg, wParam, lParam ) );
}
return 0;
}
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// Register our Window class
WNDCLASS wndclass;
wndclass.style = CS_VREDRAW | CS_HREDRAW;
wndclass.lpfnWndProc = &WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = NULL;
wndclass.hbrBackground = reinterpret_cast <HBRUSH> (COLOR_BTNFACE + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName =windowClassName;
::RegisterClass(&wndclass);
// Create our main, raw win32 API window
// We create the window invisible (meaning that we do not provide WS_VISIBLE as the window style parameter), because making it visible and then
// adding a HwndSource will make it flicker.
HWND mainWindow = ::CreateWindow(
windowClassName,
windowTitle,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
windowWidth,
windowHeight,
NULL,
NULL,
hInstance,
0);
::ShowWindow (mainWindow, nCmdShow);
::UpdateWindow( mainWindow );
typedef HRESULT (WINAPI *PFonc)(IUnknown*, HWND,IUnknown**);
HINSTANCE hDLL2 = ::LoadLibrary(TEXT("atl.dll"));
if (!hDLL2)
return 1;
PFonc AtlAxAttachControl = (PFonc) ::GetProcAddress(hDLL2,"AtlAxAttachControl");
RECT rect;
::GetClientRect(mainWindow,&rect);
container = ::CreateWindowEx(
WS_EX_CLIENTEDGE,
L"EDIT",
L"",WS_CHILD | WS_VISIBLE,
0,
0,
rect.right,
rect.bottom,
mainWindow,
0,
hInstance,
0);
HRESULT hr = ::CoInitialize(0);
IWebBrowser2 *pIwb;
hr = ::CoCreateInstance(CLSID_WebBrowser,0,CLSCTX_ALL,IID_IWebBrowser2,(void**)&pIwb);
hr = AtlAxAttachControl(pIwb,container,0);
if(FAILED(hr))
{
MessageBox(0, L"FAILED(AtlAxAttachControl(pitd, container, NULL))", L"Error", MB_ICONERROR | MB_OK);
}
pIwb->GoHome();
pIwb->Navigate2((VARIANT*)L"www.google.com",0,0,0,0);
// Start message processing
::MSG message;
while (::GetMessageA(&message, 0, 0, 0))
{
switch (message.message) {
case WM_QUIT:
break;
default:
::TranslateMessage(& message);
::DispatchMessage(& message);
break;
}
}
CoUninitialize();
FreeLibrary(hDLL2);
return 0;
}

I test out duDE's code and it works except it did not browse to the requested URL.
I am quite surprise that ocx can be used in win32 without ATL/MFC so easily in this way, but it actually works.
I think the failure to browse is because:
pIwb->Navigate2((VARIANT*)L"www.google.com",0,0,0,0);
Change it to:
// create variant for url
VARIANT varUrl;
// init variant
VariantInit(&varUrl);
varUrl.vt = VT_BSTR;
varUrl.bstrVal = SysAllocString(L"www.google.com");
// browse to url
hr = pIwb->Navigate2((VARIANT*)&varUrl,0,0,0,0);
// release variant
VariantClear(&varUrl);

Related

WM_HOVER not working with WinAPI ListView

I have a ListView drawing to the screen. Now, I am trying to have a function called when the user hovers over the items. I am trying to use WM_HOVER right now because it seems the most straight foward; however, it doesn't seem to be working. I got WM_CLICK to work fine, but not for the hovering.
Will WM_HOVER do what I need it to, or should I be looking into something else such as TrackMouseEvent()?
Here is some example code. Really the only pertinent part, I believe, are the lines in the WndProc() following case WM_HOVER:
//libraries
#pragma comment ("lib", "Comctl32.lib")
#pragma comment ("lib", "d2d1.lib")
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <vector>
#include <string>
#include <dwrite.h>
#include <d2d1.h>
#include <commctrl.h>
#include <strsafe.h>
#define IDS_APP_TITLE 103
#define IDR_MAINFRAME 128
#define IDD_PRACTICE_DIALOG 102
#define IDD_ABOUTBOX 103
#define IDM_EXIT 105
#define IDI_PRACTICE 107
#define IDI_SMALL 108
#define IDC_PRACTICE 109
#define IDC_MYICON 2
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
#define MAX_LOADSTRING 100
#define PROJECT_LIST_VIEW 110
BOOL mouseTracking = false;
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
std::vector<std::string> stringsVector = { "String1", "String2", "String3" };
//D2D1 pointers
ID2D1Factory* m_pD2DFactory;
ID2D1DCRenderTarget* m_pRenderTarget;
ID2D1SolidColorBrush* m_pBlackBrush;
//dimension variables
int w, h;
RECT rc;
HWND listViewHandle;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
HRESULT CreateDeviceResources(HWND hwnd, HDC hdc);
bool onRender(HWND hwnd, PAINTSTRUCT* ps);
///////////////////
//Function to insert the items into the list view
//////////////////
BOOL InsertListViewItems(HWND hWndListView, int cItems);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_PRACTICE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PRACTICE));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
//Create the List View Control
listViewHandle = CreateWindow(WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_EDITLABELS, 100, 100, 500, 500, hWnd, (HMENU)PROJECT_LIST_VIEW, hInst, NULL);
InsertListViewItems(listViewHandle, stringsVector.size());
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
{
HDC hdc = BeginPaint(hWnd, &ps);
onRender(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
}
case WM_SIZE:
{
if (m_pRenderTarget)
{
m_pRenderTarget->Release();
m_pRenderTarget = nullptr;
}
break;
}
////////////////////////////////////////////
//
// HERE ARE THE MOUSE MOVE CASES
//
/////////////////////////////////////////////
case WM_MOUSEHOVER:
{
OutputDebugStringA("HOVER\n");
mouseTracking = FALSE;
break;
}
case WM_MOUSEMOVE:
if (!mouseTracking)
{
// start tracking if we aren't already
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.hwndTrack = listViewHandle; //This is the handle to the ListView window
tme.dwHoverTime = HOVER_DEFAULT;
mouseTracking = TrackMouseEvent(&tme);
}
break;
case WM_MOUSELEAVE:
mouseTracking = FALSE;
break;
case WM_NOTIFY:
{
NMLVDISPINFO* plvdi;
switch (((LPNMHDR)lParam)->code)
{
case NM_CLICK:
OutputDebugStringA("CLICK\n");
break;
case LVN_GETDISPINFO:
{
////////////////////
//This is the callback that sets the pszText attribute of the items
////////////////////
plvdi = (NMLVDISPINFO*)lParam;
const char* inString = stringsVector[plvdi->item.iItem].c_str();
size_t size = strlen(inString) + 1;
wchar_t* outString = new wchar_t[size];
size_t outSize;
mbstowcs_s(&outSize, outString, size, inString, size - 1);
LPWSTR ptr = outString;
StringCchCopy(plvdi->item.pszText, plvdi->item.cchTextMax, outString);
delete[] outString;
break;
}
}
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PRACTICE));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PRACTICE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&m_pD2DFactory
);
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//////////////////
//Function to insert the items into the list view
//////////////////
BOOL InsertListViewItems(HWND hWndListView, int cItems)
{
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
// Initialize LVITEM members that are common to all items.
// Initialize LVITEM members that are different for each item.
lvc.iSubItem = 0;
lvc.pszText = (LPWSTR)L"test";
lvc.cx = 200;
// Insert items into the list.
if (ListView_InsertColumn(hWndListView, 0, &lvc) == -1)
return FALSE;
LVITEM lvI;
// Initialize LVITEM members that are common to all items.
lvI.pszText = LPSTR_TEXTCALLBACK; //This should send an LVN_GETDISPINFO message
lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
lvI.stateMask = 0;
lvI.iSubItem = 0;
lvI.state = 0;
// Initialize LVITEM members that are different for each item.
for (int index = 0; index < cItems; index++)
{
lvI.iItem = index;
lvI.iImage = index;
// Insert items into the list.
if (ListView_InsertItem(hWndListView, &lvI) == -1)
return FALSE;
}
return TRUE;
}
HRESULT CreateDeviceResources(HWND hwnd, HDC hdc)
{
HRESULT hr = S_OK;
if (!m_pRenderTarget) { //If m_pRenderTarget changes size
// Create a DC render target.
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(
DXGI_FORMAT_B8G8R8A8_UNORM,
D2D1_ALPHA_MODE_IGNORE),
0,
0,
D2D1_RENDER_TARGET_USAGE_NONE,
D2D1_FEATURE_LEVEL_DEFAULT
);
hr = m_pD2DFactory->CreateDCRenderTarget(&props, &m_pRenderTarget);
GetClientRect(hwnd, &rc);
if (SUCCEEDED(hr))
hr = m_pRenderTarget->BindDC(hdc, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
w = size.width;
h = size.height;
if (SUCCEEDED(hr))
{//position objects
// Create a black brush
hr = m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &m_pBlackBrush);
}
}
return hr;
}
bool onRender(HWND hwnd, PAINTSTRUCT* ps)
{
HDC hdc = ps->hdc;
HRESULT hr;
hr = CreateDeviceResources(hwnd, hdc);
if (SUCCEEDED(hr))
{
m_pRenderTarget->BeginDraw();
m_pRenderTarget->SetTransform(D2D1::IdentityMatrix());
m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
hr = m_pRenderTarget->EndDraw();
}
SetWindowPos(listViewHandle, HWND_TOP, w * .1, h * .1, w * .3, h * .3, SWP_SHOWWINDOW);
SendMessage(listViewHandle, LVM_SETCOLUMNWIDTH, 0, w * .2);
if(SUCCEEDED(hr))
return true;
return false;
}
As dxiv said, If you need to handle NM_HOVER message, you need to add LVS_EX_TRACKSELECT style:
ListView_SetExtendedListViewStyle(listViewHandle, LVS_EX_TRACKSELECT);
If you don't want to choose hover but only want to handle hover, you can refer to:How can I detect if the mouse is over an item/subitem in a List View control?
Edit:
According to : TrackMouseEvent tracks mouse events in your window, but only if the events belong to your window
So you need to subclass your ListView and handle its window procedure:
WNDPROC oldListViewProc; //A global variable
oldListViewProc = (WNDPROC)SetWindowLongPtr(listViewHandle, GWL_WNDPROC, (LONG_PTR)ListViewProc);
......
LRESULT CALLBACK ListViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_MOUSEHOVER:
{
OutputDebugStringA("HOVER\n");
return 0;
}
case WM_MOUSEMOVE:
if (!mouseTracking)
{
// start tracking if we aren't already
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.hwndTrack = hwnd; //This is the handle to the ListView window
tme.dwHoverTime = HOVER_DEFAULT;
mouseTracking = TrackMouseEvent(&tme);
}
break;
case WM_MOUSELEAVE:
mouseTracking = FALSE;
break;
}
return CallWindowProc(oldListViewProc, hwnd, msg, wParam, lParam);
}

Putting an Image on Screen After Choosing it from File Explorer winapi

I am trying to write code where the user is able to choose an image from their computer. I was able to get a piece of code working where the window would update itself when the user choosed an image. So, I went ahead and added some buttons to the screen and now, the image wont even load onto the screen. I'm confused as to why. It's not the image size because I chose a small image to load in as well.
Here is my function for putting the image up:
void putImage(HDC hdc, HWND hWnd)
{
Graphics graphic(hdc);
Image* image = Image::FromFile(filePath);
Status status = graphic.DrawImage(image, 10, 20);
RECT updateRect = { 0 };
updateRect.left = 10;
updateRect.top = 10;
updateRect.right = updateRect.left + image->GetWidth();
updateRect.bottom = updateRect.top + image->GetHeight();
RedrawWindow(hWnd, &updateRect, NULL, RDW_INVALIDATE);
}
And here's my paint:
case WM_PAINT: {
PAINTSTRUCT ps;
HDC screen = BeginPaint(hWnd, &ps);
HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
if (hbuff)
{
RECT rc;
GetClientRect(hWnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
putImage(screen, hWnd);
hr = EndBufferedPaint(hbuff, TRUE);
}
EndPaint(hWnd, &ps); } break;
I just added the buttons with CreateWindowW with WS_VISIBLE and WS_CHILD.
If you set the absolute path of the file, your code will work. It is worth mentioning that you can comment RedrawWindow, because this function will repeatedly refresh the window and cause flicker.
This is a reproducible example, you can try:
#include <Windows.h>
#include <ObjIdl.h>
#include <gdiplus.h>
#include <uxtheme.h>
#include <shobjidl_core.h>
#pragma comment (lib,"Gdiplus.lib")
#pragma comment(lib,"Uxtheme")
#define MAX_LOADSTRING 100
#define IDB_BUTTON1 101
using namespace Gdiplus;
using namespace std;
void putImage(HDC, HWND);
void Opendialog();
HWND hwnd;
PWSTR pszFilePath;
BOOL flag = 0;
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message)
{
case WM_CREATE:
{
HWND hwndButton = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
L"OK", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
500, // x position
10, // y position
100, // Button width
100, // Button height
hwnd, // Parent window
(HMENU)IDB_BUTTON1, // No menu.
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
NULL); // Pointer not needed.
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDB_BUTTON1:
Opendialog();
flag = 1;
InvalidateRect(hwnd, NULL, FALSE);
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
HRESULT hr = S_OK;
PAINTSTRUCT ps;
HDC screen = BeginPaint(hwnd, &ps);
// TODO: Add any drawing code that uses hdc here...
if (flag == 1)
{
HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
if (hbuff)
{
RECT rc;
GetClientRect(hwnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
putImage(screen, hwnd);
hr = EndBufferedPaint(hbuff, TRUE);
}
flag = 0;
}
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
};
HINSTANCE hinst;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow) {
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
//Initialize GDI+
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
hinst = GetModuleHandle(NULL);
// create a window class:
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = hinst;
wc.lpszClassName = L"win32";
// register class with operating system:
RegisterClass(&wc);
// create and show window:
hwnd = CreateWindow(L"win32", L"My program", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 0, 0, 1000, 800, NULL, NULL, hinst, NULL);
if (hwnd == NULL) {
return 0;
}
ShowWindow(hwnd, SW_SHOW);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void putImage(HDC hdc, HWND hWnd)
{
Graphics graphic(hdc);
Image* image = Image::FromFile(pszFilePath);
Status status = graphic.DrawImage(image, 10, 20);
RECT updateRect = { 0 };
updateRect.left = 10;
updateRect.top = 10;
updateRect.right = updateRect.left + image->GetWidth();
updateRect.bottom = updateRect.top + image->GetHeight();
// RedrawWindow(hWnd, &updateRect, NULL, RDW_INVALIDATE);
}
void Opendialog()
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |
COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
IFileOpenDialog* pFileOpen;
// Create the FileOpenDialog object.
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
if (SUCCEEDED(hr))
{
// Show the Open dialog box.
hr = pFileOpen->Show(NULL);
// Get the file name from the dialog box.
if (SUCCEEDED(hr))
{
IShellItem* pItem;
hr = pFileOpen->GetResult(&pItem);
if (SUCCEEDED(hr))
{
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
// Display the file name to the user.
if (SUCCEEDED(hr))
{
// MessageBox(NULL, pszFilePath, L"File Path", MB_OK);
CoTaskMemFree(pszFilePath);
}
pItem->Release();
}
}
pFileOpen->Release();
}
CoUninitialize();
}
}
Debug:
Updated:
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <string>
#include<string.h>
#include <iostream>
#include <uxtheme.h>
#include <shobjidl.h>
#include <objidl.h>
#include <gdiplus.h>
#include <gdiplusheaders.h>
#pragma comment (lib,"Gdiplus.lib")
#pragma comment (lib, "uxtheme.lib")
#pragma comment(lib, "user32.lib")
#pragma warning(disable:4996)
using namespace Gdiplus;
#define FILE_OPEN 1
#define FILE_MENU_EXIT 3
#define MENU_HELP 4
static TCHAR szWindowClass[] = _T("DesktopApp");
static TCHAR szTitle[] = _T("Multi-Purpose Media Editor");
HINSTANCE hInst;
HMENU hMenu;
PWSTR filePath;
int flag = 0;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void AddMenus(HWND);
void AddControls(HWND);
void OpenFileWindow(HWND);
void putImage(HDC, HWND);
std::wstring s2ws(const std::string&);
//Main Function for Windows Desktop Application
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
hInst = hInstance;
DEVMODE settings;
EnumDisplaySettings(NULL, 0, &settings);
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
NULL,
NULL,
hInstance,
NULL
);
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
ShowWindow(hWnd, nCmdShow);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HRESULT hr;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
AddMenus(hWnd);
AddControls(hWnd);
hr = BufferedPaintInit();
break;
case WM_COMMAND:
switch (wParam)
{
case FILE_MENU_EXIT:
// File Menu Exit
DestroyWindow(hWnd);
break;
case FILE_OPEN:
OpenFileWindow(hWnd);
flag = 1;
InvalidateRect(hWnd, NULL, FALSE);
break;
}
break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC screen = BeginPaint(hWnd, &ps);
/*Gdiplus::Graphics gf(screen);
Gdiplus::Bitmap jpgicon(L"jpg-icon.png");
Gdiplus::Bitmap pdficon(L"pdf-icon.png");
gf.DrawImage(&jpgicon, 10, 10);
gf.DrawImage(&pdficon, 900, 10);*/
if (flag)
{
HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
if (hbuff)
{
RECT rc;
GetClientRect(hWnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
//DrawText(screen, L"Multi-Purpose Media Editor", -1, &rc, DT_BOTTOM | DT_VCENTER | DT_SINGLELINE);
putImage(screen, hWnd);
hr = EndBufferedPaint(hbuff, TRUE);
}
flag = 0;
}
EndPaint(hWnd, &ps); } break;
case WM_DESTROY:
BufferedPaintUnInit();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
void AddMenus(HWND hWnd)
{
hMenu = CreateMenu();
HMENU hFileMenu = CreateMenu();
HMENU hSubMenu = CreateMenu();
// File Open Submenu
/*AppendMenu(hSubMenu, MF_STRING, FILE_OPEN_JPG, s2ws("JPG").c_str());
AppendMenu(hSubMenu, MF_STRING, FILE_OPEN_PDF, s2ws("PDF").c_str());*/
// File Popup Menu
// (UINT_PTR)hSubMenu <- for submenu
AppendMenu(hFileMenu, MF_POPUP, FILE_OPEN, s2ws("Open").c_str());
AppendMenu(hFileMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hFileMenu, MF_STRING, FILE_MENU_EXIT, s2ws("Exit").c_str());
// Main Menu
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, s2ws("File").c_str());
AppendMenu(hMenu, MF_STRING, MENU_HELP, s2ws("Help").c_str());
SetMenu(hWnd, hMenu);
}
void AddControls(HWND hWnd)
{
// Static and Edit Controls
CreateWindowW(L"static", L"Multi-Purpose Media Editor", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER, GetSystemMetrics(SM_CXSCREEN) / 2, 10, 180, 30, hWnd, NULL, NULL, NULL);
// Button on Window
//CreateWindowW(L"button", L"JPG Editor", WS_VISIBLE | WS_CHILD, 190, 150, 100, 30, hWnd, NULL, NULL, NULL);
//CreateWindowW(L"button", L"PDF Editor", WS_VISIBLE | WS_CHILD, 770, 150, 100, 30, hWnd, NULL, NULL, NULL);
CreateWindowW(L"button", L"Edit Image", WS_VISIBLE | WS_CHILD, GetSystemMetrics(SM_CXSCREEN) / 4, 3 * GetSystemMetrics(SM_CYSCREEN) / 4, 100, 30, hWnd, (HMENU)FILE_OPEN, NULL, NULL);
CreateWindowW(L"button", L"Edit PDF", WS_VISIBLE | WS_CHILD, 3 * GetSystemMetrics(SM_CXSCREEN) / 4, 3 * GetSystemMetrics(SM_CYSCREEN) / 4, 100, 30, hWnd, NULL, NULL, NULL);
}
void OpenFileWindow(HWND hWnd)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
IFileOpenDialog* pFileOpen;
// Create the FileOpenDialog object.
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
if (SUCCEEDED(hr))
{
// Show the Open dialog box.
hr = pFileOpen->Show(NULL);
// Get the file name from the dialog box.
if (SUCCEEDED(hr))
{
IShellItem* pItem;
hr = pFileOpen->GetResult(&pItem);
if (SUCCEEDED(hr))
{
PWSTR pszFilePath;
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
// Display the file name to the user.
if (SUCCEEDED(hr))
{
char szBuffer[255];
WideCharToMultiByte(CP_ACP, 0, pszFilePath, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
// JPG/JPEG/PNG
if (1)
{
filePath = pszFilePath;
}
// PDF
//else if ()
//{
//}
// Error MSG
else
{
MessageBox(NULL, L"Not a supported media!", L"Error", MB_OK);
}
//LoadImageW(hInst, pszFilePath, 0, 0, 0, LR_DEFAULTSIZE);
//MessageBox(NULL, pszFilePath, L"File Path", MB_OK);
CoTaskMemFree(pszFilePath);
}
pItem->Release();
}
}
pFileOpen->Release();
}
CoUninitialize();
}
}
void putImage(HDC hdc, HWND hWnd)
{
Graphics graphic(hdc);
Image* image = Image::FromFile(filePath);
Status status = graphic.DrawImage(image, 10, 20);
RECT updateRect = { 0 };
updateRect.left = 10;
updateRect.top = 10;
updateRect.right = updateRect.left + image->GetWidth();
updateRect.bottom = updateRect.top + image->GetHeight();
//RedrawWindow(hWnd, &updateRect, NULL, RDW_INVALIDATE);
//RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}

Win 32 GUI c++ .bmp The image is not showing

I was actually following a tutorial. I really want to get an answer because I will need to add icons to the window down the line. Getting images to show in the window would be the first step.
Sorry for some reason the update I added did not go through before. My solution is geared towards Unicode.
The corrected updated file is below :
#include <windows.h>
#include <commctrl.h>
using namespace std;
LPCWSTR szClassName = L"myWindowClass";
HWND hLogo;
HBITMAP hLogoImage;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void loadPictures();
void parentControls(HWND);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int icmdshow)
{
HWND hWnd;
WNDCLASSW wc = { 0 };
wc.style = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WndProc;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hInstance = hInstance;
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.cbWndExtra = 0;
wc.cbClsExtra = 0;
if (!RegisterClassW(&wc))
{
const wchar_t Error01[] = L"Register Issue To Check On : "; /// Notice this
const wchar_t Error01_Caption[] = L"Error 01";
MessageBoxW(NULL, Error01, Error01_Caption, MB_OK | MB_ICONERROR);
return 0;
}
LPCWSTR parentWinTitle = L"My Window";
hWnd = CreateWindowW(szClassName, parentWinTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 200, NULL, NULL, NULL, NULL);
if (hWnd == NULL)
{
const wchar_t Error02[] = L"Window Creation Issue To Check On : ";
const wchar_t Error02_Caption[] = L"Window Creation Issue To Check On : ";
MessageBoxW(NULL, Error02, Error02_Caption, MB_OK | MB_ICONERROR);
}
ShowWindow(hWnd, icmdshow);
UpdateWindow(hWnd);
MSG msg = { 0 };
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
loadPictures(); /// Must be called first, Calling the Images function in Create
parentControls(hWnd);
break;
/* case WM_COMMAND:
switch (wParam)
{
}
break;
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
void parentControls(HWND hWnd)
{
hLogo = CreateWindowW(WC_STATICW, NULL, WS_VISIBLE | WS_CHILD | SS_BITMAP, 70, 25, 100, 100, hWnd, NULL, NULL, NULL);
SendMessageW(hLogo, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hLogoImage);
}
void loadPictures()
{ /// bmp image save in file with main.cpp
LPCWSTR myBmp = L"bitmap1.bmp";
hLogoImage = (HBITMAP)LoadImageW(NULL, myBmp, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
case WM_COMMAND:
switch(wp)
{
}
break;
parentControls(hWnd); <--- never gets here
loadPictures(); /// Calling the Images function in Create
break;
parentControls and loadPictures are never reached in this switch statement.
loadPictures should be called first.
Remove the two lines, put them in WM_CREATE as follows:
case WM_CREATE:
loadPictures(); /// Calling the Images function in Create
parentControls(hWnd);
break;
Someone told me the answer should be here instead of updated above. I am sure I will be made aware that it is wrong if I add it here. I figure that is why the updates didn't take when I tried them before in the original post above. Either way the update/Answer is below.
#include <windows.h>
#include <commctrl.h>
using namespace std;
LPCWSTR szClassName = L"myWindowClass";
HWND hLogo;
HBITMAP hLogoImage;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void loadPictures();
void parentControls(HWND);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int icmdshow)
{
HWND hWnd;
WNDCLASSW wc = { 0 };
wc.style = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WndProc;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hInstance = hInstance;
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.cbWndExtra = 0;
wc.cbClsExtra = 0;
if (!RegisterClassW(&wc))
{
const wchar_t Error01[] = L"Register Issue To Check On : "; /// Notice this
const wchar_t Error01_Caption[] = L"Error 01";
MessageBoxW(NULL, Error01, Error01_Caption, MB_OK | MB_ICONERROR);
return 0;
}
LPCWSTR parentWinTitle = L"My Window";
hWnd = CreateWindowW(szClassName, parentWinTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 200, NULL, NULL, NULL, NULL);
if (hWnd == NULL)
{
const wchar_t Error02[] = L"Window Creation Issue To Check On : ";
const wchar_t Error02_Caption[] = L"Window Creation Issue To Check On : ";
MessageBoxW(0, Error02, Error02_Caption, MB_OK | MB_ICONERROR);
}
ShowWindow(hWnd, icmdshow);
UpdateWindow(hWnd);
MSG msg = { 0 };
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
loadPictures(); /// Must be called first, Calling the Images function in Create
parentControls(hWnd);
break;
/* case WM_COMMAND:
switch (wParam)
{
}
break;
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
void parentControls(HWND hWnd)
{
hLogo = CreateWindowW(WC_STATICW, NULL, WS_VISIBLE | WS_CHILD | SS_BITMAP, 70, 25, 100, 100, hWnd, NULL, NULL, NULL);
SendMessageW(hLogo, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hLogoImage);
}
void loadPictures()
{ /// bmp image save in file with main.cpp
LPCWSTR myBmp = L"bitmap1.bmp";
hLogoImage = (HBITMAP)LoadImageW(NULL, myBmp, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}

SendMessage fails to send custom message to main window

Before beginning to read the problem please note i read Petzold's book (windows programming 5th edition)!
In form.h i have declared the custom message named CMessage (it stand for "custom message", which later calls the method for creating a button), in formbutton.cpp i am sending message from its constructor to the main window which is created in form.cpp. I found out from getLastError method in my helper class that send message fails because of invalid window handle, it is strange because if i use isWindow(forms.mainWindowHandle) before sending the message i got messagebox that shows "operation completed successfully". The same design worked before splitting whole code into multiple headers and cpps, now its broken.
******
step by step debugging :
form myform(hInstance);
form::form(HINSTANCE hInstanceForm);
HWND form::Createform(HWND handle, HINSTANCE hInstance, int xPos , int yPos , int xSize , int ySize);
Formbutton::Formbutton(BOOL create);
form::form();
SendMessage(forms.mainWindowHandle, CMessage,0 ,0);//error
//rest of the code and main window is shown but not the button
******
formbutton.cpp
#pragma once
#include "FormButton.h"
#include "Form.h"
#include "helper.h"
Formbutton::Formbutton(){}
Formbutton::Formbutton(BOOL create)
{
helper help;
form forms;
if (create)
{
SendMessage(forms.mainWindowHandle, CMessage,0 ,0); //same with PostMessage
help.getLastError();
}
}
HWND Formbutton::createButton(HWND button, HWND parent)
{
button = CreateWindow(TEXT("Button"), // window class name
TEXT("Button"), // window caption
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP, // window style
500, // initial x position
500, // initial y position
300, // initial x size
500, // initial y size
parent, // parent window handle
NULL, // window menu handle
(HINSTANCE)GetWindowLongPtr(parent, -6), // program instance handle
NULL); // creation parameters
ShowWindow(button, SW_SHOW);
return button;
}
form.h
#pragma once
#include <Windows.h>
#define CMessage (WM_USER+0x0001)
class form
{
private:
HWND Createform(HWND handle, HINSTANCE hInstance, int xPos = CW_USEDEFAULT, int yPos = CW_USEDEFAULT, int xSize = GetSystemMetrics(SM_CXFULLSCREEN), int ySize = GetSystemMetrics(SM_CYFULLSCREEN));
MSG msg;
WNDCLASS wndclass;
protected:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
public:
HWND mainWindowHandle;
form::form();
form::form(HINSTANCE hInstanceForm);
form::~form();
WPARAM updateForm();
};
form.cpp
#pragma once
#include "Form.h"
#include "FormButton.h"
LRESULT CALLBACK form::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
Formbutton fb;
switch (message)
{
case WM_CREATE:
return 0;
case WM_PAINT:
InvalidateRect(hwnd, &rect, TRUE);
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
SetBkMode(hdc, TRANSPARENT);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case CMessage: //this is the custom message
fb.createButton(fb.buttonHandle, hwnd);
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
HWND form::Createform(HWND handle, HINSTANCE hInstance, int xPos , int yPos , int xSize , int ySize)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = TEXT("Framework");
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
TEXT("Framework"), MB_ICONERROR);
}
handle = CreateWindow(TEXT("Framework"), // window class name
TEXT("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX | WS_HSCROLL | WS_VSCROLL, // window style
xPos, // initial x position
yPos, // initial y position
xSize, // initial x size
ySize, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
//ShowWindow(handle, SW_SHOWMAXIMIZED);
UpdateWindow(handle);
return handle;
}
WPARAM form::updateForm()
{
ShowWindow(mainWindowHandle, 10);
UpdateWindow(mainWindowHandle);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
form::form()
{
}
form::form(HINSTANCE hInstanceForm)
{
mainWindowHandle = Createform(mainWindowHandle, hInstanceForm);
}
form::~form()
{
}
helper.cpp
#pragma once
#include "helper.h"
#include <strsafe.h>
void helper::getLastError()
{
wchar_t buf[256];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL);
MessageBox(NULL, buf, TEXT("error"), MB_OK);
}
source.cpp
#pragma once
#include <Windows.h>
#include "Form.h"
#include "FormButton.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
form myform(hInstance);
Formbutton btn(true);
myform.updateForm();
}
You are creating two instances of form: one in your WinMain() and one in your Formbutton constructor. You want to add your button to the former, but you are really adding it to the latter, and the latter ceases to exist once the constructor returns.
I'm not sure how you want to structure your program, but my suggestion is to pass the correct parent form as a form * parameter to the Formbutton constructor.

C++ Win32 not retrieving edit data even though edit is in scope

I am a little new to C++, so I am starting out with a text editor program. I am developing this project in NetBeans IDE. Currently the application is all in the main source file. When I compile and run the project, I get no errors and the project proceeds to function.
However, I have some sort of error or bug that lies within the application as it is running. This bug is associated with the Edit Control and the GetWindowText() method. The problem is located in the saveFile() function. What I am making of the GetWindowText() function is to test to see if I can retrieve text from the Edit Control and use it for my needs. I tried to emulate it through a simple MessageBox() function, and I got nothing.
Source code [FULL]:
/*
* File: main.cpp
* Author: CA1K
*
* Created on November 1, 2015, 9:58 PM
*/
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <string>
using namespace std;
// [ PROGRAM PROCEDURES ]
//=========================================================
/*Really what these are used for is to address conditions to
*the WS_COMMAND case, these are registered as integers
*/
#define IDC_MAIN_EDIT 0//edit ID
#define EXIT_PROC 1//the exit procedure
#define ABOUT_PROC 2//the trigger for the "about" window
#define CLONE_PROC 3//spawn a new window
#define SAVE_PROC 4//save procedure
#define OPEN_PROC 5//copy procedure
//=========================================================
// [ DEVELOPER FRIENDLY VARIABLES ]
//=========================================================
const char g_szClassName[] = "CPadx1"; //window class name
const char g_Title[] = "CPad"; //window title
const char g_About[] = "CPad is a program developed by CA1K. It is entirely made from the win32 API. For more programs, go to ca1k.xkotto.com.";
int dim = 600;//window dimensions(square)
TCHAR buffer[512];
//=========================================================
// [ OBJECT BUILDING ]
//=========================================================
void makeMenu(HWND hwnd){
HMENU hMenubar;
HMENU hMenu;
HMENU hMenu2;
hMenubar = CreateMenu();
hMenu = CreateMenu();
hMenu2 = CreateMenu();
AppendMenuW(hMenu, MF_STRING, SAVE_PROC, L"&Save/Save as");
AppendMenuW(hMenu, MF_STRING, OPEN_PROC, L"&Open file");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, CLONE_PROC, L"&New Window");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, ABOUT_PROC, L"&About");
AppendMenuW(hMenubar, MF_POPUP, (UINT_PTR)hMenu, L"&File");
AppendMenuW(hMenu2, MF_STRING, EXIT_PROC, L"&Exit");
AppendMenuW(hMenubar, MF_POPUP, (UINT_PTR)hMenu2, L"&Config");
SetMenu(hwnd, hMenubar);
}
void dispWnd(HWND hwnd){//this function spawns a new window
HINSTANCE hInstance;
HWND newChild = CreateWindowEx(0, g_szClassName, g_Title, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, dim, dim, hwnd, NULL, hInstance, NULL);
HWND GetParent(HWND hwnd);
ShowWindow(newChild, 1);
UpdateWindow(newChild);
}
void makeEdit(HWND hwnd, HWND hEdit){//this function creates the edit
HINSTANCE hInstance;
RECT rect;
int pwidth;
int pheight;
if(GetWindowRect(hwnd, &rect))
{
pwidth = rect.right - rect.left;
pheight = rect.bottom - rect.top;
}
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","",
WS_CHILD|WS_VISIBLE|ES_AUTOVSCROLL|ES_AUTOHSCROLL|ES_MULTILINE,
0,0,pwidth,pheight,hwnd,(HMENU)IDC_MAIN_EDIT,
hInstance,NULL);
}
void saveFile(HWND hEdit){
GetWindowText(hEdit, buffer, 512);
MessageBox(NULL, buffer, "Test", MB_ICONINFORMATION);
}
//=========================================================
// [ SOFTWARE PROCESSING ]
//=========================================================
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND winEdit;
switch(msg)
{
/*WINDOW ACTIONS*/
case WM_CREATE:{//on window creation
makeMenu(hwnd);
makeEdit(hwnd,winEdit);
}
break;
case WM_SIZE:
makeEdit(hwnd,winEdit);
break;
case WM_COMMAND://window actions
switch(LOWORD(wParam))
{
case ABOUT_PROC:
MessageBox(NULL, g_About, "About", MB_ICONINFORMATION);
break;
case EXIT_PROC:
PostQuitMessage(0);//exit program
break;
case CLONE_PROC:
dispWnd(hwnd);
break;
case SAVE_PROC:
saveFile(winEdit);
break;
}
break;
case WM_CLOSE://on window close
DestroyWindow(hwnd);
break;
case WM_DESTROY://on window destroy
PostQuitMessage(0);
break;
default://default method
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
g_Title,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, dim, dim,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
//=========================================================
I am questioning whether I have the scopes wrong, or something else. Feed back would be much appreciated.
-CA1K
You need to make winEdit a static variable. This is because you use it in more than one message, like WM_CREATE and WM_COMMAND. Then, you need to pass a pointer to an HWND to your makeEdit function:
makeEdit(hwnd, &winEdit);
So your overall window procedure should look like this:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND winEdit;
switch(msg)
{
/*WINDOW ACTIONS*/
case WM_CREATE:{//on window creation
makeMenu(hwnd);
makeEdit(hwnd, &winEdit);
}
break;
case WM_SIZE:
makeEdit(hwnd,winEdit);
break;
case WM_COMMAND://window actions
switch(LOWORD(wParam))
{
case ABOUT_PROC:
MessageBox(NULL, g_About, "About", MB_ICONINFORMATION);
break;
case EXIT_PROC:
PostQuitMessage(0);//exit program
break;
case CLONE_PROC:
dispWnd(hwnd);
break;
case SAVE_PROC:
saveFile(winEdit);
break;
}
break;
case WM_CLOSE://on window close
DestroyWindow(hwnd);
break;
case WM_DESTROY://on window destroy
PostQuitMessage(0);
break;
default://default method
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}