Win32调控台应用程序,vs2017新建项目并未mfc

图片 10

图片 1

改造MFC类

  • CCEFDemoDoc 不需改动
  • CMFCCEFView
    • 添加头文件CClientHandler.hMFCCEFDoc.h
    • 添加继承public ClientHandler::Delegate,并添加其虚函数

    virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser) override;

    // Called when the browser is closing.
    virtual void OnBrowserClosing(CefRefPtr<CefBrowser> browser) override;

    // Called when the browser has been closed.
    virtual void OnBrowserClosed(CefRefPtr<CefBrowser> browser) override;

    // Set the window URL address.
    virtual void OnSetAddress(std::string const & url) override;

    // Set the window title.
    virtual void OnSetTitle(std::string const & title) override;

    // Set fullscreen mode.
    virtual void OnSetFullscreen(bool const fullscreen) override;

    // Set the loading state.
    virtual void OnSetLoadingState(bool const isLoading,
        bool const canGoBack,
        bool const canGoForward) override;

void CCEFDemoView::OnBrowserCreated(CefRefPtr<CefBrowser> browser)
{
    m_browser = browser;
}

void CCEFDemoView::OnBrowserClosing(CefRefPtr<CefBrowser> browser)
{
}

void CCEFDemoView::OnBrowserClosed(CefRefPtr<CefBrowser> browser)
{
    if (m_browser != nullptr &&
        m_browser->GetIdentifier() == browser->GetIdentifier())
    {
        m_browser = nullptr;
        m_clientHandler->DetachDelegate();
    }
}

void CCEFDemoView::OnSetAddress(std::string const & url)
{
    auto main = static_cast<CMainFrame*>(m_wndMain);
    if (main != nullptr)
    {
        auto newurl = CString{ url.c_str() };
        if (newurl.Find(m_startUrl) >= 0)
            newurl = "";

        //main->SetUrl(newurl);
    }
}

void CCEFDemoView::OnSetTitle(std::string const & title)
{
    ::SetWindowText(m_hWnd, CefString(title).ToWString().c_str());
}

void CCEFDemoView::OnSetFullscreen(bool const fullscreen)
{
}

void CCEFDemoView::OnSetLoadingState(bool const isLoading,
    bool const canGoBack,
    bool const canGoForward)
{
}

void CCEFDemoView::OnInitialUpdate()
{
    CView::OnInitialUpdate();

    InitStartUrl();

    auto rect = RECT{ 0 };
    GetClientRect(&rect);

    CefWindowInfo info;
    info.SetAsChild(GetSafeHwnd(), rect);

    CefBrowserSettings browserSettings;
    browserSettings.web_security = STATE_DISABLED;

    m_clientHandler = new ClientHandler(this);
    m_clientHandler->CreateBrowser(info, browserSettings, CefString(m_startUrl));
}

void CCEFDemoView::OnSize(UINT nType, int cx, int cy)
{
    CView::OnSize(nType, cx, cy);

    if (m_clientHandler != nullptr)
    {
        if (m_browser != nullptr)
        {
            auto hwnd = m_browser->GetHost()->GetWindowHandle();
            auto rect = RECT{ 0 };
            GetClientRect(&rect);

            ::SetWindowPos(hwnd, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
        }
    }
}


void CCEFDemoView::InitStartUrl()
{
    TCHAR path_buffer[_MAX_PATH] = { 0 };
    TCHAR drive[_MAX_DRIVE] = { 0 };
    TCHAR dir[_MAX_DIR] = { 0 };
    TCHAR fname[_MAX_FNAME] = { 0 };
    TCHAR ext[_MAX_EXT] = { 0 };

    ::GetModuleFileName(NULL, path_buffer, sizeof(path_buffer));
    auto err = _tsplitpath_s(path_buffer, drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME, ext, _MAX_EXT);
    if (err != 0) {}

    auto s = CString{ dir };
    s += _T("html");
    err = _tmakepath_s(path_buffer, _MAX_PATH, drive, (LPCTSTR)s, _T("index"), _T("html"));
    if (err != 0) {}

    m_startUrl = CString{ path_buffer };
    m_startUrl.Replace(_T('\'), _T('/'));
    m_startUrl = CString{ _T("file:///") } +m_startUrl;
}
  • 重写CView的OnActivateViewPreTranslateMessage函数

void CCEFDemoView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
    m_wndMain = AfxGetMainWnd();

    return CView::OnActivateView(bActivate, pActivateView, pDeactiveView);
}

//截获键盘F5消息,刷新页面
BOOL CCEFDemoView::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYDOWN)
    {
        if (pMsg->wParam == VK_F5)
        {
            m_browser->Reload();
        }
    }
    return CView::PreTranslateMessage(pMsg);
}
  • 添加OnInitialUpdateOnSize函数
  • 添加私有函数InitStartUrl和如下变量

    CefRefPtr<ClientHandler> m_clientHandler;
    CefRefPtr<CefBrowser> m_browser;
    CWnd* m_wndMain = nullptr;
    CString m_startUrl;
  • CCEFDemoView.cpp中添加消息映射ON_WM_SIZE()
  • 析构函数如下:

    if (m_clientHandler != nullptr)
        m_clientHandler->DetachDelegate();

背景

Visual Studio C++ 创建新项目蹦出来如下选项:
图片 2

Win32控制台应用程序,Win32项目,MFC有什么区别?

main.cpp

vs2017新建项目没有mfc,已经使用visualstudio安装程序勾选“MFC和ATL支持”并安装了,已有的MFC项目双击也能打开且正常显示,但是点击菜单新建—项目时却没有MFC,百度知道上没有解答.这里有没有能回答呢?

新建一个MFC SDI项目

设置为MFC标准,在静态库中使用MFC。

图片 3

新建MFC项目

正文:

  1. Win32控制台,没有界面,命令行执行生成的文件则直接在后台运行,运行效果如下:
    图片 4生成的“.exe”文件相当于Linux系统下用gcc编译出来一个“.out”文件,直接运行操作即可,只有命令符,没有界面。

  2. Win32项目
    这个就有界面了,但是界面里面的控件,基本上要自己去实现。

  3. MFC项目(Microsoft Foundation Class Library,微软基础类库)
    这个也有界面,可是界面里面的控件就不需要自己实现了,常用的控件都已经在MFC库内写好,直接拖动即可。

一、通过MFC ODBC进行操作

一、CEF简介

Chromium Embedded
Framework
(CEF)
是一个开源项目,允许在第三方应用中集成谷歌浏览器。原生支持C和C++,通过非官方扩展支持其他语言,如C#,
Java, Delphi 或
Python。本文较详细的记录了将CEF集成到MFC单文档程序的过程。

使用环境为:windows10 64位系统,visual studio 2017,按照32位编译。

参考链接

参考于知乎问答“对于一个新手来说,在使用Visual
Studio新建项目时,win32控制台应用程序和win32项目、空项目、MFC应用程序有哪些区别?”
“杜小豆”答主的回答,感谢。

至此,记录完毕。

记录时间:2017-1-19
记录地点:深圳WZ

至此,数据源添加完毕

二、准备工作

下载CEF,最新版本在http://cefbuilds.com/下载,但好像被墙了,我一直没法登陆,后来在下载链接下载到cef_binary_3.2171.1901_windows32

图片 5

Paste_Image.png

解压到任意目录,用VS2017打开cefclient2010.sln,升级到VS2017格式。编译其中的libcef_dll_wrapper项目,会出现以下错误。

图片 6

Paste_Image.png

产生原因为:SDK中的solution文件是用VS2010产生的,我的VS版本为VS2017,转换后,有些Project编译选项中,Treat
Warnings As
Errors(把警告看作错误来处理)选项开启了。按照下图,把此选项关闭,就可以正常编译了。

图片 7

Paste_Image.png

编译成功后,在outDebuglib
这个目录里会生成一个文件:libcef_dll_wrapper.lib,这个文件在开发我们项目的时候会使用。

 

复制资源文件

cef_binary_3.2171.1901_windows32Resources目录下的文件,拷贝到程序的Debug目录

图片 8

Paste_Image.png

运行生成的程序,可得如下界面,说明成功。

图片 9

Paste_Image.png

2、如果使用的mysql是64位的,需要将项目的解决方案平台由win32改成x64

准备CEF文件

  • cef_binary_3.2171.1901_windows32中的include目录拷贝到CEFDemo文件夹中。
  • cef_binary_3.2171.1901_windows32目录下Debug中的dll文件拷贝到CEFDemo的Debug目录中。
  • libcef.lib和上面生成的libcef_dll_wrapper.lib拷贝到项目文件夹下的lib目录(新建)中。
  • 配置项目属性
  • C/C++ ->常规附加包含目录$(ProjectDir)lib;$(ProjectDir)include;
  • 链接器->输入添加附加依赖项$(ProjectDir)liblibcef.lib;$(ProjectDir)liblibcef_dll_wrapper.lib;
  • Debug目录下新建一个html文件夹,并添加一个index.html用来在程序界面中呈现。

填写相关的数据库连接配置和使用的数据库,可点击Test进行测试,查看是否成功连接,设置完成后点击OK

三、新建MFC项目

#include <Windows.h>
#include <iostream>
#include <iomanip>
#include <sql.h>
#include <odbcss.h>
#include <sqlext.h>
#define MAXBUFLEN   255 
#define MaxNameLen  20

#import "c:program filescommon filessystemadomsado15.dll" no_namespace rename("EOF", "adoEOF")

SQLHENV  henv = SQL_NULL_HENV;//定义环境句柄
SQLHDBC  hdbc1 = SQL_NULL_HDBC;//定义数据库连接句柄     
SQLHSTMT  hstmt1 = SQL_NULL_HSTMT;//定义语句句柄

using namespace std;
int main()
{
    RETCODE retcode;//错误返回码
    retcode = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);
    if (retcode < 0)//错误处理
    {
        cout << "allocate ODBC Environment handle errors." << endl;
        return -1;
    }
    retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
        (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
    if (retcode < 0) //错误处理
    {
        cout << "the  ODBC is not version3.0 " << endl;
        return -1;
    }
    retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);
    if (retcode < 0) //错误处理
    {
        cout << "allocate ODBC connection handle errors." << endl;
        return -1;
    }

    char* szDSN = "MySqlODBC";//添加数据源时,为其起的名字
    char* szUID = "root";
    char* szAuthStr = "123456";

    retcode = SQLConnect(hdbc1,
                        (SQLCHAR*)szDSN, 
                        (SWORD)strlen(szDSN), 
                        (SQLCHAR*)szUID, 
                        (SWORD)strlen(szUID), 
                        (SQLCHAR*)
                        szAuthStr,
                        (SWORD)strlen(szAuthStr));

    if (retcode < 0) //错误处理
    {
        cout << "connect to  ODBC datasource errors." << endl;
        return -1;
    }

    retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);
    if (retcode < 0) 
    {
        cout << "allocate ODBC statement handle errors." << endl;
        return -1;
    }
    retcode = SQLExecDirect(hstmt1, (SQLCHAR*)"SElECT *  FROM book", SQL_NTS);
    if (retcode < 0)
    {
        cout << "Executing statement  throught ODBC  errors." << endl;
        return -1;
    }
    SQLCHAR      bookname[MaxNameLen + 1];
    SQLCHAR         size[MaxNameLen + 1];
    SQLLEN         columnLen = 0;

    retcode = SQLBindCol(hstmt1, 2, SQL_C_CHAR, bookname, MaxNameLen, &columnLen);
    retcode = SQLBindCol(hstmt1, 3, SQL_C_CHAR, size, MaxNameLen, &columnLen);
    while ((retcode = SQLFetch(hstmt1)) != SQL_NO_DATA)
    {
        cout <<setw(9) <<"BookName:" << bookname << endl;
        cout << setw(9) << "Size:" << size << endl;
    }
    system("pause");
}

添加必要的类

添加ClientHandler类,具体如下:

#pragma once

#include "include/base/cef_lock.h"
#include "include/cef_client.h"

class ClientHandler : public CefClient,
    public CefDisplayHandler,
    public CefLifeSpanHandler,
    public CefLoadHandler
{
public:
    // Implement this interface to receive notification of ClientHandler
    // events. The methods of this class will be called on the main thread.
    class Delegate
    {
    public:
        // Called when the browser is created.
        virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser) = 0;

        // Called when the browser is closing.
        virtual void OnBrowserClosing(CefRefPtr<CefBrowser> browser) = 0;

        // Called when the browser has been closed.
        virtual void OnBrowserClosed(CefRefPtr<CefBrowser> browser) = 0;

        // Set the window URL address.
        virtual void OnSetAddress(std::string const & url) = 0;

        // Set the window title.
        virtual void OnSetTitle(std::string const & title) = 0;

        // Set fullscreen mode.
        virtual void OnSetFullscreen(bool const fullscreen) = 0;

        // Set the loading state.
        virtual void OnSetLoadingState(bool const isLoading,
            bool const canGoBack,
            bool const canGoForward) = 0;

    protected:
        virtual ~Delegate() {}
    };

public:
    ClientHandler(Delegate* delegate);
    ~ClientHandler();

    void CreateBrowser(CefWindowInfo const & info, CefBrowserSettings const & settings, CefString const & url);

    // CefClient methods:
    virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() override { return this; }
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
    virtual CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }

    // CefDisplayHandler methods:
    virtual void OnAddressChange(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& url) override;
    virtual void OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) override;
    virtual void OnFullscreenModeChange(CefRefPtr<CefBrowser> browser, bool fullscreen);

    // CefLifeSpanHandler methods:
    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
    virtual bool DoClose(CefRefPtr<CefBrowser> browser) override;
    virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;

    // CefLoadHandler methods:
    virtual void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
        bool isLoading,
        bool canGoBack,
        bool canGoForward) override;

    virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
        CefRefPtr<CefFrame> frame,
        ErrorCode errorCode,
        const CefString& errorText,
        const CefString& failedUrl) override;

    // This object may outlive the Delegate object so it's necessary for the
    // Delegate to detach itself before destruction.
    void DetachDelegate();

private:

    // Include the default reference counting implementation.
    IMPLEMENT_REFCOUNTING(ClientHandler);
    // Include the default locking implementation.
    IMPLEMENT_LOCKING(ClientHandler);

private:
    Delegate* m_delegate;
};

#include "stdafx.h"
#include "ClientHandler.h"


#include <sstream>
#include <string>

#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"

ClientHandler::ClientHandler(Delegate* delegate)
    : m_delegate(delegate)
{
}

ClientHandler::~ClientHandler()
{
}

void ClientHandler::CreateBrowser(CefWindowInfo const & info, CefBrowserSettings const & settings, CefString const & url)
{
    CefBrowserHost::CreateBrowser(info, this, url, settings, nullptr);
}

void ClientHandler::OnAddressChange(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& url)
{
    CEF_REQUIRE_UI_THREAD();

    // Only update the address for the main (top-level) frame.
    if (frame->IsMain())
    {
        if (m_delegate != nullptr)
            m_delegate->OnSetAddress(url);
    }
}

void ClientHandler::OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title)
{
    CEF_REQUIRE_UI_THREAD();

    if (m_delegate != nullptr)
        m_delegate->OnSetTitle(title);
}

void ClientHandler::OnFullscreenModeChange(CefRefPtr<CefBrowser> browser, bool fullscreen)
{
    CEF_REQUIRE_UI_THREAD();

    if (m_delegate != nullptr)
        m_delegate->OnSetFullscreen(fullscreen);
}

void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{
    CEF_REQUIRE_UI_THREAD();

    if (m_delegate != nullptr)
        m_delegate->OnBrowserCreated(browser);
}

bool ClientHandler::DoClose(CefRefPtr<CefBrowser> browser)
{
    CEF_REQUIRE_UI_THREAD();

    if (m_delegate != nullptr)
        m_delegate->OnBrowserClosing(browser);

    return false;
}

void ClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{
    CEF_REQUIRE_UI_THREAD();

    if (m_delegate != nullptr)
        m_delegate->OnBrowserClosed(browser);
}

void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
    CefRefPtr<CefFrame> frame,
    ErrorCode errorCode,
    const CefString& errorText,
    const CefString& failedUrl)
{
    CEF_REQUIRE_UI_THREAD();

    // Don't display an error for downloaded files.
    if (errorCode == ERR_ABORTED)
        return;

    // Display a load error message.
    std::stringstream ss;
    ss << "<html><body bgcolor="white">"
        "<h2>Failed to load URL " << std::string(failedUrl) <<
        " with error " << std::string(errorText) << " (" << errorCode <<
        ").</h2></body></html>";
    frame->LoadString(ss.str(), failedUrl);
}

void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> browser, bool isLoading, bool canGoBack, bool canGoForward)
{
    CEF_REQUIRE_UI_THREAD();

    if (m_delegate != nullptr)
        m_delegate->OnSetLoadingState(isLoading, canGoBack, canGoForward);
}

void ClientHandler::DetachDelegate()
{
    m_delegate = nullptr;
}

 

修改CCEFDemoApp

  • 修改头文件
    • 添加引用include/cef_base.hinclude/cef_app.h
    • 重写函数ExitInstance()PumpMessage()

int CCEFDemoApp::ExitInstance()
{
    AfxOleTerm(FALSE);
    UninitializeCef();
    return CWinApp::ExitInstance();
}

BOOL CCEFDemoApp::PumpMessage()
{
    auto result = CWinApp::PumpMessage();
    CefDoMessageLoopWork();
    return result;
}
  • 添加私有函数和变量:InitializeCef()UninitializeCef(),和CefRefPtr<CefApp> m_app

void CCEFDemoApp::InitializeCef()
{
    CefMainArgs mainargs(m_hInstance);
    CefSettings settings;
    settings.multi_threaded_message_loop = false;
    CefInitialize(mainargs, settings, m_app, nullptr);
}
void CCEFDemoApp::UninitializeCef()
{
    CefShutdown();
}
  • 修改源文件
    • 添加头文件引用CEFDemoView.h
    • InitInstanceCWinApp::InitInstance();之前添加InitializeCef();初始化CEF
    • 添加公有函数void SetUrl(CString const & url)
    • 添加消息映射afx_msg void OnClose()
    • 添加私有成员CCEFDemoView* GetView()

既然使用到了ODBC那么就要需要添加数据源了

图片 10

项目中使用的数据库名和表数据请参考C++操作mysql方法总结(1)中的介绍

 

 

相关文章

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图