728x90

1.웹뷰2의 환경 설정 및 기본 샘플 빌드 방법

 

Get started with WebView2 in Win32 apps - Microsoft Edge Developer documentation

Get started building WebView2 for Win32 by working with sample apps and the WebView2 SDK.

learn.microsoft.com

 

2.위 샘플에서 WebView2에 대한 소스 코드

// <-- WebView2 sample code starts here -->
// Step 3 - Create a single WebView within the parent window
// Locate the browser and set up the environment for WebView
CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, nullptr,
    Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
        [hWnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT 
        {
            // Create a CoreWebView2Controller and 
            // get the associated CoreWebView2 whose parent is the main window hWnd
            env->CreateCoreWebView2Controller(
                hWnd, 
                Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
                [hWnd](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT 
                {
                    if (controller != nullptr) 
                    {
                        webviewController = controller;
                        webviewController->get_CoreWebView2(&webview);
                    }
                    
                    // Add a few settings for the webview
                    // The demo step is redundant since the values are the default settings
                    wil::com_ptr<ICoreWebView2Settings> settings;
                    webview->get_Settings(&settings);
                    settings->put_IsScriptEnabled(TRUE);
                    settings->put_AreDefaultScriptDialogsEnabled(TRUE);
                    settings->put_IsWebMessageEnabled(TRUE);
                    
                    // Resize WebView to fit the bounds of the parent window
                    RECT bounds;
                    GetClientRect(hWnd, &bounds);
                    webviewController->put_Bounds(bounds);

                    // Schedule an async task to navigate to Bing
                    webview->Navigate(L"https://www.bing.com/");

                    return S_OK;
                }).Get());
            return S_OK;
        }).Get());

 

WebView2의 코드는 Callback 기반으로 동작한다.

 

// Step 4 - Navigation events
// register an ICoreWebView2NavigationStartingEventHandler to cancel any non-https navigation
EventRegistrationToken token;
webview->add_NavigationStarting(Callback<ICoreWebView2NavigationStartingEventHandler>(
    [](ICoreWebView2* webview, ICoreWebView2NavigationStartingEventArgs* args) -> HRESULT 
    {
        wil::unique_cotaskmem_string uri;
        args->get_Uri(&uri);
        std::wstring source(uri.get());
        if (source.substr(0, 5) != L"https") 
        {
            args->put_Cancel(true);
        }
        return S_OK;
    }).Get(), &token);
  • Navigate할 때 이벤트를 등록할 수 있다
  • 위에 코드는 Navigation을 시작할 때 uri가 https 가 아니면 사이트를 열지 않겠다는 이벤트를 등록한다

 

// Step 5 - Scripting
// Schedule an async task to add initialization script that freezes the Object object
webview->AddScriptToExecuteOnDocumentCreated(L"Object.freeze(Object);", nullptr);
// Schedule an async task to get the document URL
webview->ExecuteScript(L"window.document.URL;", Callback<ICoreWebView2ExecuteScriptCompletedHandler>(
    [](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT 
    {
        LPCWSTR URL = resultObjectAsJson;
        //doSomethingWithURL(URL);
        return S_OK;
    }).Get());
  • WebView2 컨트롤에 JavaScript 코드를 삽입할 수 있다
  • 삽입된 JavaScript는 JavaScript가 제거될 때까지 모든 새로운 최상위 문서와 모든 하위 프레임에 적용된다

 

// Step 6 - Communication between host and web content
// Set an event handler for the host to return received message back to the web content
webview->add_WebMessageReceived(Callback<ICoreWebView2WebMessageReceivedEventHandler>(
    [](ICoreWebView2* webview, ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT 
    {
        wil::unique_cotaskmem_string message;
        args->TryGetWebMessageAsString(&message);
        // processMessage(&message);
        webview->PostWebMessageAsString(message.get());
        return S_OK;
    }).Get(), &token);

// Schedule an async task to add initialization script that
// 1) Add an listener to print message from the host
// 2) Post document URL to the host
webview->AddScriptToExecuteOnDocumentCreated(
    L"window.chrome.webview.addEventListener(\'message\', event => alert(event.data));" \
    L"window.chrome.webview.postMessage(window.document.URL);",
    nullptr);
  • 호스트와 웹 콘텐츠의 통신도 가능하다 (postMessage)
  • Web -> Host
    • WebView2 컨트롤 내에서 실행되는 웹 콘텐츠는 메서드를 통해 호스트에 게실될 수 있으며 window.chrome.webview.postMessage는 호스트에 등록된 ICoreWebView2WebMessageReceivedEventHandler 이벤트 핸들러에 의해 처리된다
  • Host -> Web
    • ICoreWebView2::PostWebMessageAsString
    • ICoreWebView2::PostWebMessageAsJSON
    • 위 메서드를 통해 웹 콘텐츠에 메시지를 보낼 수 있으며 이 메시지는 리스너에 추가된 핸들러에 의해 포착된다
    • window.chrome.webview.addEventListener 이 통신 메커니즘을 사용하면 호스트에 기본 API를 실행하도록 요청하는 메시지를 전달하여 웹 콘텐츠가 기본 기능을 사용할 수 있다
  • 메커니즘을 이해하기 위한 예로 WebView2에서 문서 URL을 출력하려고하면 다음 단계가 발생한다
    • 호스트는 수신된 메시지를 웹 콘텐츠로 다시 반환하기 위한 핸들러를 등록합니다.
    • 호스트는 호스트에서 메시지를 인쇄하기 위해 핸들러를 등록하는 스크립트를 웹 콘텐츠에 삽입합니다.
    • 호스트는 호스트에 URL을 게시하는 웹 콘텐츠에 스크립트를 삽입합니다.
    • 호스트의 핸들러가 트리거되어 메시지(URL)를 웹 콘텐츠에 반환합니다.
    • 웹 콘텐츠의 핸들러가 트리거되고 호스트(URL)의 메시지를 인쇄합니다.
728x90

'Basic Programming > WebView2' 카테고리의 다른 글

WebView2 - 참고 사이트들  (0) 2024.05.19
728x90
728x90

'Basic Programming > WebView2' 카테고리의 다른 글

WebView2 - WebView2GettingStarted 코드 분석  (0) 2024.05.19
728x90

다른 글 이외에 잡다하지만 유용해 보이는 것들에 대해 정리...

 

https://en.cppreference.com/w/cpp/utility/source_location

 

std::source_location - cppreference.com

struct source_location; (since C++20) The std::source_location class represents certain information about the source code, such as file names, line numbers, and function names. Previously, functions that desire to obtain this information about the call sit

en.cppreference.com

 

https://en.cppreference.com/w/cpp/utility/functional/bind_front

 

std::bind_front, std::bind_back - cppreference.com

template< class F, class... Args > constexpr /* unspecified */ bind_front( F&& f, Args&&... args ); (1) (since C++20) template< auto ConstFn, class... Args > constexpr /* unspecified */ bind_front( Args&&... args ); (2) (since C++26) template< class F, cla

en.cppreference.com

 

https://en.cppreference.com/w/cpp/types/is_constant_evaluated

 

std::is_constant_evaluated - cppreference.com

constexpr bool is_constant_evaluated() noexcept; (since C++20) Detects whether the function call occurs within a constant-evaluated context. Returns true if the evaluation of the call occurs within the evaluation of an expression or conversion that is mani

en.cppreference.com

 

https://en.cppreference.com/w/cpp/atomic/atomic_ref

 

std::atomic_ref - cppreference.com

template< class T > struct atomic_ref; (1) (since C++20) template< class T > struct atomic_ref ; (2) (since C++20) The std::atomic_ref class template applies atomic operations to the object it references. For the lifetime of the std::atomic_ref object, the

en.cppreference.com

 

https://en.cppreference.com/w/cpp/experimental/atomic_shared_ptr

 

std::experimental::atomic_shared_ptr - cppreference.com

Merged into ISO C++ The functionality described on this page was merged into the mainline ISO C++ standard as of 11/2017; see std::atomic > (since C++20) template< class T > class atomic_shared_ptr; (concurrency TS) The class template atomic_shared_ptr pro

en.cppreference.com

 

https://en.cppreference.com/w/cpp/thread/counting_semaphore

 

std::counting_semaphore, std::binary_semaphore - cppreference.com

template< std::ptrdiff_t LeastMaxValue = /* implementation-defined */ > class counting_semaphore; (1) (since C++20) using binary_semaphore = std::counting_semaphore<1>; (2) (since C++20) 1) A counting_semaphore is a lightweight synchronization primitive th

en.cppreference.com

 

https://en.cppreference.com/w/cpp/thread/latch

 

std::latch - cppreference.com

class latch; (since C++20) The latch class is a downward counter of type std::ptrdiff_t which can be used to synchronize threads. The value of the counter is initialized on creation. Threads may block on the latch until the counter is decremented to zero.

en.cppreference.com

 

https://en.cppreference.com/w/cpp/thread/barrier

 

std::barrier - cppreference.com

template< class CompletionFunction = /* see below */ > class barrier; (since C++20) The class template std::barrier provides a thread-coordination mechanism that blocks a group of threads of known size until all threads in that group have reached the barri

en.cppreference.com

 

 

https://en.cppreference.com/w/cpp/io/basic_osyncstream

 

std::basic_osyncstream - cppreference.com

The class template std::basic_osyncstream is a convenience wrapper for std::basic_syncbuf. It provides a mechanism to synchronize threads writing to the same stream. It can be used with a named variable: { std::osyncstream synced_out(std::cout); // synchro

en.cppreference.com

 

 

728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - jthread  (0) 2024.01.21
C++20 - format  (0) 2024.01.20
C++20 - Time Zone  (0) 2024.01.20
C++20 - Calendar  (0) 2024.01.17
C++20 - 비트연산  (0) 2024.01.17
728x90

그 동안 std::thread를 사용한 예제를 보면 다음과 같다

void ThreadWork()
{
    while(true)
    {
        // work...
    }
};

int main()
{
    std::thread t(ThreadWork);
    
    // 쓰레드가 종료되길 기다려줘야 한다.
    if (t.joinable())
    {
        t.join();
    }
}

 

이번에 jthread는 쉽게 말하면 소멸자에서 join을 해준다. 즉 위의 코드를 아래와 같이 변경할 수 있다.

void ThreadWork()
{
    while(true)
    {
        // work...
    }
};

int main()
{
    std::jthread t(ThreadWork);
}

 

 

하지만 위의 코드들은 thread가 종료되지 않는다. 종료되는 코드를 추가하면 다음과 같다.

bool gRunning =true;

void ThreadWork()
{
    while(gRunning)
    {
        // work...
    }
};

int main()
{
    std::thread t(ThreadWork);
    
    // 쓰레드 종료 요청
    gRunning = false;
    
    // 쓰레드가 종료되길 기다려줘야 한다.
    if (t.joinable())
    {
        t.join();
    }
}

 

jthread를 이용하면 조금 더 우아하게 종료할 수 있게 된다.

void ThreadWork(std::stop_token stopToken)
{
    while(true)
    {
        if (stopToken.stop_requested())
            break;
    }
};

int main()
{
    std::jthread t(ThreadWork);
    
    t.request_stop();
}

 

그 동안 사용했던 std::thread를 좀 더 관리하기 쉬워질 것 같다.

728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - 그 외 함수들...  (0) 2024.01.21
C++20 - format  (0) 2024.01.20
C++20 - Time Zone  (0) 2024.01.20
C++20 - Calendar  (0) 2024.01.17
C++20 - 비트연산  (0) 2024.01.17
728x90

C++을 좀 사용해보신분들은 이미 fmt::format을 많이 쓰고 있었을거라고 생각한다.

이제 동일한 기능이 C++20에도 포함이 되었다.

// format : format string 반환
auto str = std::format("{}, {}, {}", 1, 1.1, asdf);

// format_to : 결과를 output iterator에 반환
std::string buffer;
format_to(std::back_inserter(buffer), "{}, {}, {}", 1, 1.1, asdf);

// format_to_n : 최대 n개의 문자를 output iterator에 반환
std::string buffer2;
format_to(std::back_inserter(buffer2), 2, "{}, {}, {}", 1, 1.1, asdf);

 

만약 문자열에 "{" 를 사용하고 싶으면 {{ 와 같이 두개를 사용하면된다.

auto str = format("{{asdf {}}}", 5);

 

순서 지정하는 방법

format("{}, {}, {}", 10, 20, 30);
format("{1}, {0}, {2}", 10, 20, 30);

 

빈칸 채우는 문자 지정 (default : space)
정렬
 < left : 숫자가 아니면 default
 > right : 숫자면 default
 ^ center

format("{:10}", 5);   // "         5"
format("{:*<10}", 5); // "5*********"
format("{:*>10}", 5); // "*********5"
format("{:*^10}", 5); // "****5*****"

 

부호 (정수나 부동소수점에 사용)
 + : 양수면 + 붙여라
 - : 음수면 - 붙여라

format("{0:}, {0:+}, {0:-}", 0) // 0, +0, 0
format("{0:}, {0:+}, {0:-}", 1) // 1, +1, 1
format("{0:}, {0:+}, {0:-}", -1) // -1, -1, -1

 

정수에 대한 이진수, 팔진수, 십육진수 표현
 b : 이진수
 미지정 : 팔진수
 x : 십육진수
 #015 : 0을 15개의 padding 추가

format("#015", 0x78)  "000000000000120"
format("#015b", 0x78) "0b0000001111000"
format("#015x", 0x78) "0x0000000000078"

 

위에서 {:10} 은 최소 10개를 만든다는 뜻이었다. 반대로 최대 갯수도 지정할 수 있다.
precision 부동소수점과 문자열의 최대 갯수를 지정

double d = 123.456789;

format("{:.50}", d);            // "123.45678900000000555777....."
format("{:.8}", d);             // "123.45679" - 반올림됨
format("{:.5}", d);             // "123.46" - 반올림됨
format("{:.5}", "Hello World");	// "Hello"

 

타입 지정
 s : string
 b : binary 0b로 시작
 B : b와 같지만 0B로 시작
 d : decimal
 o : octal
 x : hexadecimal 0x로 시작
 X : x와 같지만 0X로 시작
 부동소수점 관련 (e, E, f, F ,g, G) : 생략... (지수 표시, 정밀도 등등...)


728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - 그 외 함수들...  (0) 2024.01.21
C++20 - jthread  (0) 2024.01.21
C++20 - Time Zone  (0) 2024.01.20
C++20 - Calendar  (0) 2024.01.17
C++20 - 비트연산  (0) 2024.01.17
728x90

전 세계에서 사용하는 프로그램을 개발할 때 시간이 관련된 작업을 하게 될 것이다.

이때 Local Time으로 시간 계산을 하게되면 나라마다의 시차를 계산하기 어려워진다.

그렇기 때문에 UTC(Coordinated Universal Time 협정 세계시)를 이용하여 시간을 계산하게 된다

- 영국 : UTC+0.00 (Greenwich Mean Time, GMT)
- 한국 : UTC+9.00
- 뉴욕 : UTC-5.00
...

이렇듯 각 나라마다 시간 계산을 해줘야하는데, 드디어 C++20에서 지원해주게 되었다.

using namespace std;
using namespace std::chrono;

auto utcTime :: system_clock::now();
cout << utcTime << endl;

auto localTime = zoned_time(current_zone(), utcTime);
cout << localTime << endl;

auto localTime2 = zoned_time("Asia/Shanghai"s, utcTime);
cout << localTime2 << endl;

 

추가로 유닉스 시간이라는 개념에 대해서 알아둬야한다.

유닉스 시간(Unix Time)은 시각을 나타내는 방식이고, POSIX, Epoch 시간이라고도 부른다.
1970년 1월 1일 00:00:00 협정 세계시(UTC) 부터의 경과 시간을 초로 환산하여 정수로 나타낸 것이다.

using namespace std;
using namespace std::chrono;

auto utcTime = system_clock::now();

int64_t hoursSinceUtc = duration<hours>(utcTime.time_since_epoch()).count();
int64_t utcEpoch = duration<seconds>(utcTime.time_since_epoch()).count();
728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - jthread  (0) 2024.01.21
C++20 - format  (0) 2024.01.20
C++20 - Calendar  (0) 2024.01.17
C++20 - 비트연산  (0) 2024.01.17
C++20 - erase, erase_if  (1) 2023.12.29
728x90

이번에 chrono에 시간관련 라이브러리가 추가되었다

매우 사용하기 쉬우니... 한번 돌려보면 바로 이해 될 듯...

// hh_mm_ss : duration since midnight, split into hours, minutes, seconds, fractional seconds

auto timeOfDay = std::chrono::hh_mm_ss(12.5h + 32min + 100s + 0.6s);
cout << timeOfDay << endl;
cout << timeOfDay.hours() << endl;
cout << timeOfDay.minutes() << endl;
cout << timeOfDay.seconds() << endl;
cout << timeOfDay.subseconds() << endl;
cout << timeOfDay.to_duration() << endl;

// Calendar Date
using namespace chrono;
chrono::year_month_day ymd1{year(2021), month(11), day(14)};
chrono::year_month_day ymd2{year(2021)/month(11)/day(14)};
chrono::year_month_day ymd3{2021y, November, 14d};
cout << ymd1 << endl;
	
// 해당 년/월의 마지막날을 가져오는 방법
// year/month/day
// day/month/year
// month/day/year
std::chrono::year_month_day_last ymdl1 = 2021y / November / last;
std::chrono::year_month_day_last ymdl2 = last / November / 2021y;
std::chrono::year_month_day_last ymdl3 = November / last / 2021;
auto d1 = ymdl1.day();
chrono::year_month_day ymd4{ymdl1};

// 해당 년/월의 4번째 금요일 날짜 가져오는 방법
std::chrono::year_month_weekday ymwkd1{year(2021)/November/Friday[4]};
chrono::year_month_day ymd5{ ymwkd1 };

// timepoint
time_point timePoint = chrono::sys_days(ymd1);

// Cute Syntax
// 2021y, 30d, January, February, ... December

// Validation
std::chrono::day d{31};
d++;
bool valid = d.ok();

auto leapYear2000{year(2000)/2/29};
auto leapYear2001{year(2001)/2/29};
auto leapYear2002{year(2002)/2/29};

bool valid2 = leapYear2000.ok(); // true
bool valid3 = leapYear2001.ok(); // false
bool valid4 = leapYear2002.ok(); // false

auto now = std::chrono::system_clock::now();
auto diff = floor<chrono::hours>(now) - sys_days(1987y / January / 30d);

 

 

728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - format  (0) 2024.01.20
C++20 - Time Zone  (0) 2024.01.20
C++20 - 비트연산  (0) 2024.01.17
C++20 - erase, erase_if  (1) 2023.12.29
C++20 - Template Parameter for Lambda  (0) 2023.12.28
728x90

그 동안 사용했던 비트연산을 요약하면 다음과 같다

enum Type
{
    test = 3
};

unsigned int bit = 0;

// 추가
bit |= (1 << test);

// 포함 여부 확인
bool check = (bit & (1 << test));

// 삭제
bit &= ~(1 << test);

// 토글
bit ^= (1 << test);

 

좀 더 편하게 사용해라고 이번에 C++20에서 비트연산에 대한 다양한 함수들이 추가되었다.

 

엔디안 확인 기능

// 리틀 엔디안, 빅 엔디안 등등을 확인할 수 있다.
if (std::endian::native == std::endian::little)
{
    cout << "little" << endl;
}
else
{
    cout << "big" << endl;
}

 

그 외에 추가된 함수들...

// bit_cast : 새로운 캐스팅
// has_single_bit	: 어떤 숫자가 2^n 형태인지 (2의 거듭제곱)
// popcount : unsigned int 숫자에서 1의 개수
// bit_ceil : 해당 값보다 작지 않은 (2의 거듭제곱)중 제일 작은 것 (floor < num < ceil)
// bit_floor : 해당 값보다 크지 않은 (2의 거듭제곱)중 제일 큰 것 (floor < num < ceil)
// bit_width : 해당 값을 표현하기 위해 필요한 최소 비트 개수
// rotl : bitwise left-rotation
// rotr : bitwise right-rotation
// countl_zero : 제일 큰 비트부터 시작해서, 연속된 0의 개수
// countl_one : 제일 큰 비트부터 시작해서, 연속된 1의 개수
// countr_zero : 제일 작은 비트부터 시작해서, 연속된 0의 개수
// countr_one : 제일 작은 비트부터 시작해서, 연속된 1의 개수

std::uint8_t num = 0b00110010;
cout << boolalpha;

cout << std::has_single_bit(num) << endl; // false
cout << popcount(num) << endl; // 3
cout << std::bitset<8>(std::bit_ceil(num)) << endl; // 0b01000000
cout << std::bitset<8>(std::bit_floor(num)) << endl; // 
cout << std::bit_width(5u) << endl; // width(0x000101) = 3
cout << std::bitset<8>(std::rotl(num, 2)) << endl; // 0b11001000
cout << std::bitset<8>(std::rotr(num, 2)) << endl; // 0b10001100
cout << countl_zero(num) << endl; // 2
cout << countl_one(num) << endl; // 0
cout << countr_zero(num) << endl; // 1
cout << countr_one(num) << endl; // 0
728x90

'Basic Programming > C++ 20' 카테고리의 다른 글

C++20 - Time Zone  (0) 2024.01.20
C++20 - Calendar  (0) 2024.01.17
C++20 - erase, erase_if  (1) 2023.12.29
C++20 - Template Parameter for Lambda  (0) 2023.12.28
C++20 - NonType Template Parameter  (0) 2023.12.28

+ Recent posts